Skip to main content

积累的问题

2009 年一直工作到现在开发和日常学习中能想起来的并且已经解决的 CSS 中积累的问题, 已经被淘汰不值得一提的例如 IE hack 就不会再提起了

CSS3 中 box-shadow 存在的问题

  1. CSS3box-shadow 的溢出问题 子容器加了 box-shadow 在父容器中可能存在溢出,可以通过给父元素添加 overflow:hidden 解决。
  2. box-shadow 阴影被覆盖问题
      1. 使用相对定位解决 position:relativez-index 提高层数可以把阴影显示出来
      1. 开启 gpu 加速, 设置 3d 效果 { transform: translate3d(0, 0, 0); }

CSS 中实现 0.5px 边框 解决 Android 兼容性 问题

标准1px边框
.border {
border: 1px solid #ff0000;
}
可以利用缩放-发虚
.border {
height: 1px;
background-color: red;
transform: scaleY(0.5);
}
四条边框都需要的样式
.border {
padding: 10px;
border: 1px solid red;
transform-origin: 0 0;
transform: scale(0.5, 0.5);
}
给伪元素添加设置边框
.border {
position: relative;
}
.border::before {
content: "";
position: absolute;
padding: 20px;
border: 1px solid blue;
transform-origin: 0 0;
transform: scale(0.5, 0.5);
}
利用 @media 匹配 dpr 设置边框
@media screen and (-webkit-min-device-pixel-ratio: 2) {
.border {
border-top: 0.5px solid red;
}
}

/*ios dpr=2和dpr=3情况下border相差无几,下面代码可以省略*/
@media screen and (-webkit-min-device-pixel-ratio: 3) {
.border {
border-top: 0.333333px solid red;
}
}
postcss-write-svg
@svg 1px-border {
height: 2px;
@rect {
fill: var(--color, black);
width: 100%;
height: 50%;
}
}
.border {
border: 1px solid transparent;
border-image: svg(1px-border param(--color #00b1ff)) 2 2 stretch;
}

编译之后

.border {
border: 1px solid transparent;
border-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='2px'%3E%3Crect fill='%2300b1ff' width='100%25' height='50%25'/%3E%3C/svg%3E")
2 2 stretch;
}

初始化 CSS 样式

最简单的初始化方法(强烈不建议)
* {
padding: 0;
margin: 0;
}
淘宝前端团队的样式初始化代码
body,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
p,
blockquote,
dl,
dt,
dd,
ul,
ol,
li,
pre,
form,
fieldset,
legend,
button,
input,
textarea,
th,
td {
margin: 0;
padding: 0;
}
body,
button,
input,
select,
textarea {
font: 12px/1.5tahoma, arial, \5b8b\4f53;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: 100%;
}
address,
cite,
dfn,
em,
var {
font-style: normal;
}
code,
kbd,
pre,
samp {
font-family: couriernew, courier, monospace;
}
small {
font-size: 12px;
}
ul,
ol {
list-style: none;
}
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
sup {
vertical-align: text-top;
}
sub {
vertical-align: text-bottom;
}
legend {
color: #000;
}
fieldset,
img {
border: 0;
}
button,
input,
select,
textarea {
font-size: 100%;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
style 初始化的利弊

因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对 CSS 初始化有可能会造成页面的差异。

初始化样式会对 SEO 有一定的影响,但鱼和熊掌不可兼得,但力求影响最小的情况下初始化。

CSS 里的 visibility 属性有个 collapse 属性值

  1. 对于一般的元素,它的表现跟 visibility:hidden;是一样的。元素是不可见的,但此时仍占用页面空间。
  2. 如果这个元素是 table 相关的元素,例如 table 行,table group,table 列,table column group,它的表现却跟 display:none 一样,也就是说,它们占用的空间也会释放。
  • 在不同浏览器下的区别
    • 在谷歌浏览器里,使用 collapse 值和使用 hidden 值没有什么区别。
    • 在火狐浏览器、Opera 和 IE11 里,使用 collapse 值的效果就如它的字面意思:table 的行会消失,它的下面一行会补充它的位置。

width:auto 和 width:100%的区别

  1. width:auto 会使元素撑满整个父元素,marginborderpaddingcontent 区域会自动分配水平空间。
  2. width:100% 会使元素 box 的宽度等于父元素的 content box 的宽度。
进一步解释

a

自动分配

a

设置了盒子的宽度,当内容过多时会超出父容器。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.p1 {
width: auto;
margin: 20px;
padding: 20px;
}

.p2 {
width: 100%;
margin: 20px;
padding: 20px;
}
</style>
</head>

<body>
<p class="p1">1</p>
<p class="p2">2</p>
</body>
</html>

使用图片 base64 编码的优点和缺点

base64 编码是一种图片处理格式,通过特定的算法将图片编码成一长串字符串,在页面上显示的时候,可以用该字符串来代替图片的 url 属性。

  • 优点:

    • 减少一个图片的 HTTP 请求
  • 缺点:

    • 编码后的大小会比原文件的体积大 1/3,如果把大图片编码到 HTML/CSS 中,不仅会造成文件体积的增加,影响文件的加载速度,还会增加浏览器对 HTMLCSS 文件解析渲染的时间。
    • 使用 base64 无法直接缓存,要缓存只能缓存包含 base64 的文件,比如 HTML 或者 CSS,这相比域直接缓存图片的效果要差很多。
    • 兼容性的问题,ie8以前的浏览器不支持(ZF 外包的小伙伴懂)。
详细资料可以参考

《玩转图片 base64 编码》 《前端开发中,使用 base64 图片的弊端是什么?》 《小 tip:base64:URL 背景图片与 web 页面性能优化》

css 作用域隔离方法

  1. 命名空间,加不同的前缀
.aa_container_element {
}

.bb_container_element {
}
  1. module,例如 vue 的 scoped
<style scoped></style>
  1. css-in-js
export default () => (
<div>
<h1>Hello World</h1>
<style jsx>{`
h1 {
color: red;
}
`}</style>
</div>
);
  1. Shadow DOM,其实就是 web components,作用域隔离
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>

<body>
<script>
const persions = ["luffy", "zoro", "nami", "usoop", "sanji"];

customElements.define(
"ace-conponent",
class extends HTMLElement {
connectedCallback() {
const shadow = this.attachShadow({ mode: "open" });
shadow.innerHTML = `<div>
${persions_fn(persions)}
</div>`;
}
}
);

function persions_fn(list) {
return helper_fn(list);
}

function helper_fn(list = []) {
return list
.map((ele) => `<p>${ele}</p>`)
.join(",")
.replace(/,/g, "");
}
</script>

<ace-conponent name="ace-conponent"></ace-conponent>
</body>
</html>

常见的元素隐藏方式

  1. 使用 display:none; 隐藏元素,渲染树不会包含该渲染对象,因此该元素不会在页面中占据位置,也不会响应绑定的监听事件。
  2. 使用 visibility:hidden; 隐藏元素。元素在页面中仍占据空间,但是不会响应绑定的监听事件。
  3. 使用 opacity:0; 将元素的透明度设置为 0,以此来实现元素的隐藏。元素在页面中仍然占据空间,并且能够响应元素绑定的监听事件。
  4. 通过使用绝对定位将元素移除可视区域内,以此来实现元素的隐藏。
  5. 通过 z-index 负值,来使其他元素遮盖住该元素,以此来实现隐藏。
  6. 缩小尺寸 宽高 0
  7. 通过 transform:scale(0,0) 来将元素缩放为 0,以此来实现元素的隐藏。这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。
  8. clip-path: circle(0); 元素裁剪的方法来实现元素的隐藏,这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。

多行文本溢出

.ellipsis-mute {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}

CSS 优化、提高性能的方法有哪些

  • 加载性能:

    • CSS 压缩:将写好的 CSS 进行打包压缩,可以减少很多的体积。
    • CSS 单一样式:当需要下边距和左边距的时候,很多时候选择 margin:top 0 bottom 0margin-bottom:bottom; margin-left:left; 执行的效率更高。
    • 减少使用 @import ,而建议使用 link ,因为后者在页面加载时一起加载,前者是等待页面加载完成之后再进行加载。
  • 选择器性能:

    • 关键选择器(key selector)。选择器的最后面的部分为关键选择器(即用来匹配目标元素的部分)。CSS 选择符是从右到左进行匹配的。当使用后代选择器的时候,浏览器会遍历所有子元素来确定是否是指定的元素等等;
    • 如果规则拥有 ID选择器 作为其关键选择器,则不要为规则增加标签。过滤掉无关的规则(这样样式系统就不会浪费时间去匹配它们了)。
    • 避免使用通配符,如 *{} 计算次数会很大,只对需要用到的元素进行选择。
    • 尽量少的去对标签进行选择,而是用 class
    • 尽量少的去使用后代选择器,降低选择器的权重值。后代选择器的开销是最高的,尽量将选择器的深度降到最低,最高不要超过三层,更多的使用类来关联每一个标签元素。
    • 了解哪些属性是可以通过继承而来的,然后避免对这些属性重复指定规则。
    • 尽量扁平化 CSS ,把 CSS 原子化。
  • 渲染性能:

    • 慎重使用高性能属性:浮动、定位。
    • 尽量减少页面重排、重绘。
    • 去除空规则:{}。空规则的产生原因一般来说是为了预留样式。去除这些空规则无疑能减少 CSS 文档体积。
    • 属性值为 0 时,不加单位。
    • 属性值为浮动小数 0.\*\* ,可以省略小数点之前的 0
    • 标准化各种浏览器前缀:带浏览器前缀的在前。标准属性在后。
    • CSS 雪碧图,同一页面相近部分的小图标,方便使用,减少页面的请求次数,但是同时图片本身会变大,使用时,优劣考虑清楚,再使用。
    • 正确使用 display 的属性,由于 display 的作用,某些样式组合会无效,徒增样式体积的同时也影响解析性能。例如 float 之后再设置 inline-block
    • 不滥用 web 字体。对于中文网站来说 WebFonts 可能很陌生,国外却很流行。WebFonts 通常体积庞大,而且一些浏览器在下载 WebFonts 时会阻塞页面渲染损伤性能。
  • 可维护性、健壮性:

    • BEM 规范,将具有相同属性的样式抽离出来,整合并通过 class 在页面中进行使用,提高 css 的可维护性。
    • 样式与内容分离:将 css 代码定义到外部 css 中。
BEM
  • BEM 和 SMACCS ⾮常类似,主要⽤来如何给项⽬命名。⼀个简单命名更容易让别⼈⼀起⼯作。⽐如选项卡导航是⼀个块(Block),这个块⾥的元素的是其中标签之⼀(Element),⽽当前选项卡是⼀个修饰状态(Modifier): block -代表了更⾼级别的抽象或组件

    • block__element -代表.block 的后代,⽤于形成⼀个完整的.block 的整体。

    • .block--modifier -代表.block 的不同状态或不同版本。

    • 修饰符使⽤的是_,⼦模块使⽤__符号。(不⽤⼀个-的原因是 CSS 单词连接)

举个🌰
<ul class="menu">
<li class="menu__item"></li>
<li class="menu__item_state_current"></li>
<li class="menu__item"></li>
</ul>

清除浮动的⼏种⽅式,各⾃的优缺点

  • ⽗级 div 定义 height
  • 结尾处加空 div 标签 clear:both
  • ⽗级 div 定义伪类 :afterzoom
  • ⽗级 div 定义 overflow:hidden
  • ⽗级 div 也浮动,需要定义宽度
  • 结尾处加 br 标签 clear:both
  • ⽐较好的是第 3 种⽅式,好多⽹站都这么⽤。

设置倍图

<img
srcset="images/team-photo.jpg 1x, images/team-photo-retina.jpg 2x, images/team-photo-full 2048w"
/>
background: image-set(
url(w128px.jpg) 1x,
url(w256px.jpg) 2x,
url(w512px.jpg) 3x
);