vuepress-theme-plume/docs/10.面试/面试题—css篇.md
pengzhanbo 5de60d4d6e feat(theme): plume-theme next devloping !
add plugin-auto-frontmatter | add plugin-blog-data | devloping new theme
2022-10-19 02:30:20 +08:00

7.8 KiB
Raw Blame History

title, tags, createTime, permalink, author, top, type
title tags createTime permalink author top type
面试题以及个人答案 CSS篇
面试
2022-03-26T11:46:50.028Z /article/565o1wn0 pengzhanbo false null

CSS什么是盒模型盒模型有哪些具体的表现和不同点是什么

盒模型是CSS规范定义的模块它规定了一个矩形盒子标准盒模型描述任意元素在文档树中占据的空间区域。每个盒子有四个边外边距边margin edge or outer edge边框边border edge内填充边padding edge内容边content edge or inner edge,可以划分四个区域外边距区域margin area边框区域border area内填充区域padding area内容区域content area

css box model

为什么会有盒模型类型严格来说多数浏览器都按照规范实现了标准盒模型而盒模型的类型主要是来自于不同浏览器对元素宽高的方式不同而导致IE浏览器认为元素的width/height应该是由元素的内容+内填充+边框组成而W3C规定的元素的width/height应该是元素的内容,从而衍生了不同的盒子模型。到CSS3,添加了box-sizing属性用于更改用于计算元素宽高的默认盒子模型并将IE浏览器和W3C规范纳入了实现中。可以使用此属性来模拟不正确支持CSS盒子模型规范的浏览器的行为。

注:width/height最终并不能完全决定元素的实际占用宽高。

/* 关键字值 */
box-sizing: border-box; /* 默认值 */
box-sizing: content-box;
/* 全局值 */
box-sizing: inherit;
box-sizing: initial;
box-sizing: unset;

border-box规定了元素的width内容+内填充+边框组成即IE浏览器的实现。 元素的实际占据宽度由 width属性+外边距。内容宽度为width - padding - border

content-box规定了元素的width内容宽度, W3C规范的标准。元素的实际占据宽度由widht + padding + border + margin。内容宽度为width

box-sizing还有一个待废除的值padding-boxwidthheight 属性包括内容和内边距但是不包括边框和外边距。只有Firefox实现了这个值它在Firefox 50中被删除。

在高度计算上以上规则同样适用,但对非替换行内元素,尽管内容周围存在内边距与边框,但其占用空间受到line-height属性影响。


CSS: 什么是外边距合并?什么情况下会发生外边距合并?

块元素的上外边距和下外边距有时候会发生合并,其大小取其中绝对值最大的值,这种行为叫做外边距合并。

浮动元素绝对定位元素 的外边距不会发生合并。这是因为触发了 块格式化上下文

  1. 相邻元素之间的外边距会发生合并(如果后一个元素需要清除前面的浮动,则不一定发生合并)。
  2. 父元素与其第一个子元素之间不存在边框、内边距、行内内容、没有创建 块格式化上下文、没有清除浮动或者父元素与其最后一个子元素之间不存在边框、内边距、行内内容、heigh、min-height、max-height那么子元素的外边距会溢出到父元素外面。
  3. 如果一个块级元素不包含任何内容并且在不存在边框、内边距、行内内容、heigh、min-height则该元素的上下外边距会发生合并。

三种情况的外边距合并是可以组合产生更加复杂的外边距合并情况的。

如果外边距合并的值都是负值,则合并的值为最小的外边距的值。

如果发生外边距合并的值包含负值,则合并后的值为最大的正外边距与最小的负外边距之和。


CSS垂直水平居中

这是个老生常谈的问题了,场景可以有很多,答案也有很多,答案而言其实本身不重要,重要是明白为什么这个方法为什么可以实现垂直居中。

设立一个场景:在一个宽高不固定的容器中,实现一个宽高不固定的内容盒子,并垂直水平居中。

<!-- 假设 warpper、container 宽高不固定 实现container相对于wrapper垂直水平居中-->
<div class="wrapper">
    <div class="container">
    </div>
</div>

方法一: 使用 flex 布局

.wrapper{
    display: flex;
}
.container{
    margin: auto;
}

适用于支持 flex布局的浏览器IE11以上其他现代浏览器。这里是利用flex弹性布局的特性弹性容器改变了其子元素填充可用空间的方式子元素默认从容器左上角开始排列在不设置宽高时子元素填充空间由flex声明,默认值为0 1 auto,即 flex-grow: 0;flex-shrink: 1;flex-basis: auto; 其中 flex-basis定义了子元素的宽和高的尺寸大小,auto值表示自动尺寸,根据子元素内容计算宽高,在子元素上设置margin: auto,这是利用auto平均分配水平或垂直方向上的额外的空间,从而达到目的。(此方法实现的结果是“真正的”垂直水平居中)

或者

.wrapper{
    display: flex;
    justify-content: center;
    align-content: center;
}

方法二: 使用 table 布局

.wrapper{
    display: table-cell;
    vertical-align: middle;
}
.container{
    margin: auto;
}

利用的是table布局的特性不过该方法有个缺点就是display: table-cell元素的宽高设置百分比数值是“无效的”,原因是父元素非table元素或display: table元素,display: table-cell元素的宽高百分比数字是相对于table计算的。

方法三: position + transform

.wrapper{
    position: relative;
}
.container{
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

该方法与前面两个方法的作用机理有很大的不同,首先第一点是container脱离了文档流,并且container自身的宽高发生了坍塌,在不设置宽高属性下,尺寸由内容撑开,container相对wrapper元素进行绝对定位,水平方向与垂直方向上,container的左上角顶点偏移到wrapper中点,containertransform是相对于自身的, translate(-50%, -50%)相对于自身,将左上角顶点做左上偏移自身的一半,从而实现了目的。

有一些面试者给出了container元素上设置margin-left: -50%; margin-top: -50%的答案然而margin的百分比值是相对于其父元素计算的。

方法四: 使用 行内块元素

.wrapper{
    text-align: center;
}
.wrapper:after{
    content: '';
    display: inline-block;
    vertical-align: middle;
    height: 100%;
}
.container{
    display: inline-block;
    vertical-align: middle;
    text-align: left;
}

该方法实现的垂直水平居中其实是一个近似垂直水平居中兼容IE7以上的浏览器。水平方向上.wrapper设置text-align: center;实现了水平居中;垂直方向上,给定container声明行内块元素,并vertical-align: middle,但由于container高度不确定无法声明具体的行高所以借助了父元素的伪类元素创建了一个宽度为0高度为100%的行内块元素,从而使container元素在垂直方向上实现了居中。但由于vertical-align: middle是元素的中线与字符X的中心点对齐大多数字体设计字体的中心点偏下也导致了实现的垂直居中并不是绝对的垂直居中。而要实现绝对的垂直居中需要添加一下属性

.wrapper{
    font-size: 0;
    white-space: nowrap;
}
.container{
    font-size: 14px; /* 重置回默认字体大小 */
    white-space: normal;
}

实现方法有很多,这里暂时只列出其中的四种。


想到还有其他问题继续补充...