在这篇文章我会介绍 9 个使你的 CSS 更加简洁优雅的使用技巧。这些技巧小生常用,以为挺高效实用,因此也就有了这篇文章。css
特此声明,这里说的 CSS 并不止包含 CSS,也包含 CSS 预处理器(Less Sass 等),愿各位看官不要纠结于此。html
正文如今开始。前端
咱们在设计稿还原的时候, padding 和 margin 两个是经常使用的属性,但咱们知道属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠,因此若是 margin 使用的过于频繁的时候,Box 的垂直距离可能就会发生重叠。webpack
还有一个问题就是第一个子元素的 margin-top 值会加在父元素上的 bug(最后一个子元素的 margin-bottom 也存在相似的问题)。这里是否是有人问为何呢?web
缘由就在于:express
the expression collapsing margins means that adjoining margins (no non-empty content, padding or border areas or clearance separate them) of two or more boxes (which may be next to one another or nested) combine to form a single margin.浏览器
翻译过来就是:sass
全部毗邻的两个或多个盒元素的 margin 将会合并为一个 margin 共享。 毗邻的定义为:同级或者嵌套的盒元素,而且它们之间没有非空内容、 Padding 或 Border 分隔。安全
至于为何合并我我的以为这和排队取款的安全距离有点相似,人与人之间的安全距离是 1m,若是安全距离不合并,那么咱们在排队的时候是否是人与人的距离就变成 2m 了。固然极可能不是这个缘由。性能优化
因此咱们能够在首位元素使用 padding 来替代 margin。固然有的时候使用 padding 不能知足需求,这时你也能够在“非空内容”这个条件作文章。即在父元素添加一个伪元素。
因此咱们在使用 margin 的时候必定要注意 collapsing margins 问题。
不知道曾经的你是否是遇到吸顶效果,就是使用 position:fixed 这个属性。其实若是其父元素中有使用 transform, fixed 的效果会降级为 absolute。
既然会降级为 absolute 效果,咱们该怎么解决这个问题呢?咱们就改考虑什么状况下 fixed 和 absolute 的表现效果会是同样的。
即当使用 fixed 的直接父元素的高度和屏幕的高度相同时 fixed 和 absolute 的表现效果会是同样的。
若是这个直接父级内的元素存在滚动的状况,那就加上 overflow-y:auto。
在 CSS 中有许多距离单位,好比 px | em | rem | %,还有 CSS3 中的 vh | vw 等单位。
那么咱们在项目中应该如何使用呢?咱们在 pc 端不须要考虑的这么复杂,因此这里咱们主要讲讲这些单位在移动端中的使用。
px 是咱们最先接触到的单位了,不过咱们在移动端自适应的要求下,使用的频率不是很高;我总结了如下使用的状况:
好比须要咱们画一个 r 为 5px 的圆,若是咱们使用 rem 做为单位,咱们很快会发如今一些机型上的图案不圆,会呈现椭圆形。这是因为 rem 转 px 会存在精度丢失问题。
因此这个时候咱们就须要使用 px 配合 dpr 来实现:
// less /*@size 建议取双数*/ .circle(@size, @backgroundColor) { width: @size; height: @size; background-color: @backgroundColor; [data-dpr="1"] & { width: @size * 0.5; height: @size * 0.5; } [data-dpr="3"] & { width: @size * 1.5; height: @size * 1.5; } }
这个问题下面我会单独作一小节讲,在这里就不累述。
通常状况字体的大小我也会使用 rem 做为单位,由于精度丢失我认为在能够接受的范围以内。
rem 是 CSS3 新增的一个相对单位(root em),即相对 HTML 根元素的字体大小的值。
rem 应该是自适应使用的最普遍的单位了。
em 也是一个相对单位,倒是相对当前元素的字体大小。
通常建议在 line-height 使用 em。由于在须要调整字体大小的时候,只需修改 font-size 的值,而 line-height 已经设置成了相对行高了。
在存在首行缩进的需求,我也会使用这个单位。
text-indent: 2em
vw: 1vw = 视口宽度的 1% vh: 1vh = 视口高度的 1%
咱们知道以 rem 单位设计的弹性布局,是须要在头部加载一段脚原本进行监听分辨率的变化来动态改变根元素字体大小,使得 CSS 与 JS 耦合了在一块儿。
那么有没有方案解决这个耦合的问题呢?
答案就是视口单位 vw | vh。
如下就是前人给出的使用方案:
$vm_fontsize: 75; @function rem($px) { @return ($px / $vm_fontsize ) * 1rem; } $vm_design: 750; html { font-size: ($vm_fontsize / ($vm_design / 2)) * 100vw; @media screen and (max-width: 320px) { font-size: 64px; } @media screen and (min-width: 540px) { font-size: 108px; } } // body 也增长最大最小宽度限制,避免默认100%宽度的 block 元素跟随 body 而过大太小 body { max-width: 540px; min-width: 320px; }
通常设计稿中的某一类的文字(元素)都是用相同的字体大小、颜色、行高等样式属性,因此这些值咱们没必要每次都重复写,由于当 UI 更新设计方案,你须要改的地方就不少了。这些重复使用的值咱们彻底能够存放在变量里面。
Sass 和 Less 稍微有点区别:
// sass $direction: left; // less @direction: left;
固然 CSS 原生也是存在变量的,使用规则以下:
变量定义的语法是: --; // *为变量名称。 变量使用的语法是:var();
不管是变量的定义和使用只能在声明块 {} 里面
:root { --blue_color: #3388ff; --main_bgcolor: #fafafa; --font_size_12: 12px; --font_size_14: 14px; --color: 20px; } .div1{ background-color: var(--main_bgcolor); font-size: var(--font_size_12); }
和重复变量同样,重复的样式也能够归类。我以为优秀的代码其中有一条确定是代码的复用性强。
以前咱们写 CSS 的时候,也会将一些重复使用的代码放在一个 class 中,这样的确达到了必定的复用性,不过最后的效果可能就是在一个元素里面放了不少 class,以下图:
这样下一个接手得人不免会有点迷糊,并且这样会形成样式愈来愈难修改。
这个时候,mixin( 能够理解成 class 中的 class )就能发挥它的做用了。
这是一个描述性文字的样式:
.font-description { .font-des-style(24px,#fff,1.5em); .line-camp(2); } // less /* 多行显示 */ .line-camp( @clamp:2 ) { text-overflow: -o-ellipsis-lastline; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: @clamp; -webkit-box-orient: vertical; } .font-des-style( @fontSize, @color, @lineHeight, @textAlign:left ) { font-size: @fontSize; color: @color; line-height: @lineHeight; text-align: @textAlign; }
这只是一个简单的例子,咱们能够把可复用的样式放在 mixin 中,这样接手项目的人只须要熟悉你写的 mixin.less 就能够开始迭代需求了。
作过移动端需求的前端确定是避免不了处理 1px 细线问题,这个问题的缘由就是 UI 对页面美观度的要求愈来愈高(不要和我说这是 retina 屏的问题)。
据小生所知好像没有什么兼容性特别好的方案,这里我只是提供两种种相对较好的方案。
.border_bottom { overflow: hidden; position: relative; border: none!important; } .border_bottom:after { content: "."; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; background-color: #d4d6d7; -webkit-transform-origin: 0 0; transform-origin: 0 0; -webkit-transform: scaleY(0.5); transform: scaleY(0.5); }
固然这个方案在一些版本较低的机型也是会出现粗细不均、细线消失断裂的兼容性问题。不过如今在已经 2019 年了,版本较低的机型也淘汰的差很少了。
.border_bottom { box-shadow: inset 0px -1px 1px -1px #d4d6d7; }
这个方案基本能够知足全部场景,不过有个缺点也就是颜色会变浅。
在大多数状况下咱们在设置元素的 border 和 padding 并不但愿改变元素的 width,height 值,这个时候咱们就能够为该元素设置 box-sizing:border-box;。
我不但愿每次都重写一遍,而是但愿他是继承而来的,那么咱们可使用以下代码:
html { box-sizing: border-box; } *, *:before, *:after { box-sizing: inherit; }
这样的好处在于他不会覆盖其余组件的 box-sizing 值,又无需为每个元素重复设置 box-sizing:border-box;。
性能优化中有一个重要的指标 —— 首次有效绘制(FMP),即指页面的首要内容(primary content)出如今屏幕上的时间。这一指标影响用户看到页面前所需等待的时间,而 内联首屏关键 CSS(即 Critical CSS,能够称之为首屏关键 CSS) 能给用户一个更好的心理预期。
如图:
咱们知道内联 CSS 可以使浏览器开始页面渲染的时间提早,即在 HTML 下载完成以后就能渲染了。
既然是内联关键 CSS,也就说明咱们只会将少部分的 CSS 代码直接写入 HTML 中。至于内联哪些 CSS 你可使用 Critical。
需求中咱们也常常遇到这样的需求,这里直接提供方案。
超出省略
.line-camp( @clamp:2 ) { text-overflow: -o-ellipsis-lastline; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: @clamp; -webkit-box-orient: vertical; }
-webkit-box-orient:vertical 在使用 webpack 打包的时候这段代码会被删除掉,缘由是optimize-css-assets-webpack-plugin 这个插件的问题。
可使用以下的写法:
.line-camp( @clamp:2 ) { text-overflow: -o-ellipsis-lastline; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: @clamp; /*! autoprefixer: off */ -webkit-box-orient: vertical; /* autoprefixer: on */ }
// html <div>姓名</div> <div>手机号码</div> <div>帐号</div> <div>密码</div> // css div { margin: 10px 0; width: 100px; border: 1px solid red; text-align-last: justify; }
效果以下:
《前端词典》这个系列会持续更新,每一期我都会讲一个出现频率较高的知识点。但愿你们在阅读的过程中能够斧正文中出现不严谨或是错误的地方,本人将不胜感激;若经过本系列而有所得,本人亦将不胜欣喜。
若是你以为个人文章写的还不错,能够关注个人微信公众号,公众号里会提早剧透呦。
你也能够添加个人微信 wqhhsd, 欢迎交流。
在接下来的几篇文章中我会介绍 Vue 相关