这个是菜鸟笔试的时候碰见的题,本来想归为笔试,但是感觉这个挺重要的,直接单独拿出来写比较好!
padding的%以谁为基准
<div style="width: 300px;height: 200px;">
<div style="width: 100px;height: 50px;padding: 5%;background-color: black;box-sizing: border-box;">
<div style="width: 100%;height: 100%;background-color: white;"></div>
</div>
</div>
运行结果:

由此可以发现padding是按照父元素的宽度确定的!如果没有父元素,那就是窗口宽度!
这里去掉box-sizing也是一样的:

margin的%以谁为基准
<div style="width: 300px;height: 200px;">
<div style="width: 100px;height: 50px;margin: 5%;box-sizing: border-box;">
<div style="width: 100%;height: 100%;background-color: red;"></div>
</div>
</div>
运行结果:

由此可以发现margin是按照父元素的宽度确定的!如果没有父元素,那就是窗口宽度!
同padding,去掉box-sizing也是一样的!
(2023年12月6号 补) 其实这里描述并不正确,其实%是以包含块来决定的,包含块的定义见该文档:前端css之包含块
包含块重点内容
包含块分为两种,一种是根元素(HTML 元素)所在的包含块,被称之为初始包含块(initial containing block)。对于浏览器而言,初始包含块的的大小等于视口 viewport 的大小,基点在画布的原点(视口左上角)。它是作为元素绝对定位和固定定位的参照物。
另外一种是对于非根元素,对于非根元素的包含块判定就有几种不同的情况了。大致可以分为如下几种:
- 如果元素的 positiion 是 relative 或 static ,那么包含块由离它最近的块容器(block container)的内容区域(content area)的边缘建立。
- 如果 position 属性是 fixed,那么包含块由视口建立。
- 如果元素使用了 absolute 定位,则包含块由它的最近的 position 的值不是 static (也就是值为fixed、absolute、relative 或 sticky)的祖先元素的内边距区的边缘组成。
前面两条实际上都还比较好理解,第三条往往是初学者容易比较忽视的,我们来看一个示例:
<body>
<div class="container">
<div class="item">
<div class="item2"></div>
</div>
</div>
</body>
.container {
width: 500px;
height: 300px;
background-color: skyblue;
position: relative;
}
.item {
width: 300px;
height: 150px;
border: 5px solid;
margin-left: 100px;
}
.item2 {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
left: 10px;
top: 10px;
}
首先阅读上面的代码,然后你能在脑海里面想出其大致的样子么?或者用笔和纸画一下也行。
公布正确答案:
怎么样?有没有和你所想象的对上?
其实原因也非常简单,根据上面的第三条规则,对于 div.item2 来讲,它的包含块应该是 div.container,而非 div.item。
如果你能把上面非根元素的包含块判定规则掌握,那么关于包含块的知识你就已经掌握 80% 了。
实际上对于非根元素来讲,包含块还有一种可能,那就是如果 position 属性是 absolute 或 fixed,包含块也可能是由满足以下条件的最近父级元素的内边距区的边缘组成的:
- transform 或 perspective 的值不是 none
- will-change 的值是 transform 或 perspective
- filter 的值不是 none 或 will-change 的值是 filter(只在 Firefox 下生效).
- contain 的值是 paint (例如: contain: paint;)
我们还是来看一个示例:
<body>
<div class="container">
<div class="item">
<div class="item2"></div>
</div>
</div>
</body>
.container {
width: 500px;
height: 300px;
background-color: skyblue;
position: relative;
}
.item {
width: 300px;
height: 150px;
border: 5px solid;
margin-left: 100px;
transform: rotate(0deg); /* 新增代码 */
}
.item2 {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
left: 10px;
top: 10px;
}
我们对于上面的代码只新增了一条声明,那就是 transform: rotate(0deg),此时的渲染效果却发生了改变,如下图所示:
可以看到,此时对于 div.item2 来讲,包含块就变成了 div.item。
好了,到这里,关于包含块的知识就基本讲完了。
两道面试题
一、方形变圆形
写到这里,突然记起来面试的一道题,就是面试官问我,有一个方形的元素,怎么把它变成圆形,当时我就很懵,现在一搜,发现就是一个border-radius属性,真的是失败!
其实这里延申一下,还可以问,怎么画出一个三角形?答案就是border
代码:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<style>
div {
width:0;
height:0;
border:100px solid;
/* 平分效果 */
/*border-color:red green blue black; */
/* 单个三角形 */
border-color:transparent transparent lightgreen transparent;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
这里要注意的就是,width和height一定要是0,不然就会出现奇奇怪怪的效果 --> 梯形!
当然,还有其它的办法,比如:canvas,svg等!更多实现三角形的可以参照:纯 CSS 实现三角形的 3 种方式
突然就想起来了一个菜鸟遇见的问题:怎么才能适配图片上不规则地带点击跳转?
望读者可以指点江山,激扬文字!
二、画0.5px的线
还有一个面试题就是,如何画出一个0.5px的线,这个菜鸟也是不会,最后想出来的是zoom(缩放),现在发现zoom是ie的特有属性,不过在goole上尝试了一下,发现可以!
下面是几种可以完成的方法(有的虽然鼠标放上去显示的是1px,但是把页面放大后是可以看到区别的):
<br>
<div style="border-top: solid 1px black;"></div>
<!-- 上面是对比用的 -->
<br>
<div style="border-top: solid 0.5px red;"></div>
<br>
<div style="height:1px;background-color:green;transform: scaleY(0.5);transform-origin: 50% 100%;"></div>
<br>
<div style="height:1px;background-color:blue;zoom: 0.5;"></div>
<br>
注意:
- 有些浏览器是支持0.5px的,但是goole不在其中,考虑适配为题还是要做的!
- transform-origin 属性:更改一个元素变形的原点
- 放大之后会有区别,第二个线会比其它三根都细,第一根 > 第三根 = 第四根 > 第二根(菜鸟不知道原因,放大之前完全不知道谁粗谁细!)
感觉菜鸟是真的菜,而且也没有读者愿意一起交流,有些问题就只能放下了,然后遗忘了,哎!心痛!T_T,感觉要是读者可以一起交流,讨论出一个很难的问题,难道不是一件幸福的事情?只能去知乎问了!
知乎回答:html画0.5px的线为什么会这样?