你不知道的CSS(上)

编写CSS样式时,其实有不少技巧能够节省HTML元素和让CSS更加的DRY,在这跟你们分享下。css

文章将分红上、中、下三篇,难度也会从简单到难,因此建议同窗们按顺序阅读起。html

文章将大量举各类示例,让同窗们能更加清楚CSS的魅力所在。前端

文章将持续输出,增长一些新奇的或者惟美的示例。。。浏览器

1. 背景与边框

1.1 半透明边框


半透明边框相信不少前端小伙伴都常常遇到过,UI设计师也常常性设计出这类样式。而若是对CSS不太熟悉的前端小伙伴人员来讲,看似简单的东西,其实有一个小坑在里面。例:bash

...
<main class="wrapper">
  <div class="border">我是边框</div>
</main>
...
  
.wrapper {
  background: black;
  ...
}
.border {
  width: 100px;
  height: 100px;
  background: white;
  border: 10px solid hsla(0, 0%, 100%, 0.3);
}
复制代码

border设置了0.3的透明度,那是否是咱们要的半透明?让咱们看看结果。app

很显然不是的,background-clip属性的初始值为border-box,意味着背景默认状况下,会侵入边框的所在的范围,当属性值设置为padding-boxsvg

.border {
  background-clip: padding-box
}
复制代码

这样就获得咱们想要的效果图了。

1.2 多重边框


box-shadow

box-shadow咱们大多数人已经用过,不太为人所知的是,它还接受第四个参数,经过设置正直或负值,可让投影面积加大或者减少。函数

.border {
  box-shadow: 0 0 0 10px red;
  ...
}
复制代码

使用box-shadow的好处在于,它接受逗号分隔语法,能够建立任意数量的投影布局

.border {
   box-shadow: 0 0 0 10px red, 0 0 0 20px yellow;
  ...
}
复制代码

惟一注意的点的是, box-shadow是层层叠加的,前者会叠加在后者之上,上例中若是 yellow须要宽度为 10px,那么须要设置为 20px

多重投影在大多数场合均可以很好的应用,但有一些注意事项。测试

投影行为跟边框不彻底一致,由于它不会影响布局,并且也不会受box-sizing属性的影响。

投影部分并不会影响鼠标事件。

outline(描边)

若是咱们只须要两层边框的话,outline(全部浏览器都支持 outline 属性)是一个不错的选择,它不会像box-shadow只能模拟实现边框。

.border {
  border: 10px solid #655;
  outline: 5px dashed deeppink;
  ...
}
复制代码

描边的另外一个好处在于,你能够经过 outline-offset属性来控制它跟元素边缘之间的间距,这个属性甚至能够接受负值。这对于某些效果来讲很是有用。举个例子

.border {
  outline: 5px solid deeppink;
  outline-offset: -79px;
}
复制代码

咋一看,是否是想到了,上传文件的按钮?

使用outline也有一些须要注意的地方。

outline 并不能接受用逗号分隔的多个值。

边框不必定会贴合 border-radius属性产生的圆角,所以若是元素是圆角的,它的描边可能仍是直角的。

1.3 灵活的背景定位


背景图片指定在容器某个区域,也是很常见。

background-position

.border {
  background: url('https://cdn.renqilai.com/2019_10_16/15_35_42.jpg') no-repeat white;
  background-size: 30px 30px;
  background-position: 60px 60px;
}
复制代码

若是在一些不支持 background-position扩展语法的浏览器上,背景图片会紧贴在左上角,看起来很奇怪,并且它会干扰到文字的可读性。提供一个回退方案也很简单,就是把老套的 bottom right 定位值写进 background 的简写属性中:

.border {
  background: url(code-pirate.svg) no-repeat bottom right #58a;
  background-position: 60px 60px;
}
复制代码

background-origin

在给背景图片设置距离某个角的偏移量时,有一种状况极其常见:偏移量与容器的内边距一致。若是采用上面提到的 background-position 的扩展语法方案,代码看起来会是这样的:

padding: 10px;
background: url(code-pirate.svg) no-repeat #58a;
background-position: 80px 80px; // 分别增长20px
复制代码

如你所见,它起做用了,但代码不够 DRY:每次改动内边距的值时,咱们都须要在三个地方更新这个值!

咱们常用background-position:top left,你是否有过疑惑,这个top left究竟是哪一个左上角?默认状况下,默认是以padding box。而咱们使用background-origin默认状况下是padding-box。若是把它的 值改为 content-box (参见下面的代码),咱们在 background-position 属 性中使用的边角关键字将会之内容区的边缘做为基准

background: url("code-pirate.svg") no-repeat #58a bottom right;
background-position: 70px 70px;
background-origin: content-box;
复制代码

不管咱们怎样更改padding值,都不会去影响图片的定位了。

calc()

从上述两例得知,咱们无非是想获得图片距离白色右边框10px,距离白色下边框10px。使用calc,它能够完美地在background-position 属性中使用:

background-origin: padding-box;
background-position: calc(100% - 20px) calc(100% - 10px);
复制代码

请不要忘记在 calc() 函数内部的 - 和 + 运算符的两侧各加一个空白符,不然会产生解析错误!这个规则如此怪异,是为了向前兼容:将来,在 calc() 内部可能会容许使用关键字,而这些关键字可能会包含连字符(即减号)

不管咱们怎样更改padding值,都不会去影响图片的布局了。

1.4 边框内圆角


若是咱们要实现内侧有圆角,外侧边框依旧保持着直角状态,如图:

咱们通常会使用两个元素实现,若是咱们须要一个元素,有没有方法实现?

在前面咱们提到过outline描边,它并不会随border-radius改变边框,依旧保持着直角状态。

outline: 5px solid deeppink;
border-radius: 10px;
box-shadow: 0 0 0 5px deeppink;
复制代码

这里box-shadow第四个参数值为5px,那这个值是如何获得的?是在某个浏览器测试的结果?事实上,指定一个等于描边宽度的扩张值在某些浏览器中可能会获得渲染异常,所以推荐一个稍小些的值。这里直接给出一个公式( 根号2 - 1)r,其中rborder-radis10px,另外有一个限制,为了让这个效果得以达成,扩张半径须要比描边的宽度值小,但它同时又要比 (根号2 - 1)r大。

1.5 条纹背景


线性渐变相信不少人都挺熟悉的,如何实现下图这种效果?

background: linear-gradient(#fb3 50%, #58a 50%);
background-size: 100% 30px;
复制代码

若是我想将黄色部分的宽度减小,我须要去修改两个值,这种也不够DRY

background: linear-gradient(#fb3 50%, #58a 0);
background-size: 100% 30px;
复制代码

将后者修改成0,那它的位置就老是会被浏览器调整为前一个色标的位置值,便可显示出相同的效果。

斜向条纹

在完成了水平以后,咱们来尝试下倾斜渐变的效果。

background: linear-gradient(45deg,#fb3 50%, #58a 0);
background-size: 30px 30px;
复制代码

很显然,这并非咱们但愿的效果。缘由在于咱们只是把每一个 贴片内部渐变旋转45度,而不是把整个重复的背景都旋转了。实际上,若是想让整个背景看起来都旋转了45度,须要单个贴片包含了四条条纹,而不是两条,只有这样才有可能作到无缝拼接。

background: linear-gradient(45deg,#fb3 25%, #58a 0, 
  #58a 50%,#fb3 0, #fb3 75%, #58a 0);
background-size: 30px 30px;
复制代码

效果出来了,而且是正确的,那若是我想要60度的?会是怎样?

background: linear-gradient(60deg,#fb3 50%, #58a 0);
复制代码

很糟糕,并非咱们想获得的一个结果。幸运的是,咱们还有更好的解决方案,一个循环式的增强版: repeating-linear-gradient()( radial-gradient()也有),色标是无限循环重复的,直到填满整个背景。

background: repeating-linear-gradient(60deg,#fb3, #fb3 15px, #58a 0, #58a 30px);
// background-size: 30px 30px;
复制代码

上例几个例子中,咱们设置同色标的开始位置和结束位置时,使用了 逗号分隔,其实这种也是能够简化的,如:

background: white repeating-linear-gradient(60deg, 
    blue 0 15px, 
    hsla(0, 0%, 0%) 0 30px, 
    red 0 45px);
复制代码

色标后有两个参数值,第一个为开始位置,第二个为结束位置。

若是咱们将第一个参数不为0会是怎样的状态?

background: white repeating-linear-gradient(60deg, 
      blue 10px 15px, 
      black 20px 30px, 
      red 0 45px);
复制代码

咱们将blue第一个参数值为10pxblack第一个参数值为20pxred保持不变。

咱们注意到,左下角再也不是以蓝色开头,而是红色开头。为何?缘由在于blue色标起始位置为10px,因此在左下角开始到10px会被重复的渐变叠加到。

而色标blueblack之间有一层渐变的过程,由于blue结束为15px,而black开始为20px,他们之间存在着5px的渐变过程。

灵活的同色系条纹

大多数状况下,若是咱们想要的条纹图案色差不是差别极大的状况下,只是明度有着轻微的差别。举个例子,咱们来看看这个条纹图案:

background: repeating-linear-gradient(30deg,
#79b, #79b 15px, #58a 0, #58a 30px);
复制代码

条纹是由一个主色调( #58a)和它的浅色变体所组成的。可是,这两种颜色之间的关系在代码中并无体现出来。此外,若是咱们想要改变这个条纹的主色调,甚至须要修改四处!

幸运的是,还有一种更好的方法:再也不为每种条纹单独指定颜色,而是 把最深的颜色指定为背景色,同时把半透明白色的条纹叠加在背景色之上来 获得浅色条纹:

background: #58a;
background-image: repeating-linear-gradient(30deg,hsla(0,0%,100%,.1),
  hsla(0,0%,100%,.1) 15px,transparent 0, transparent 30px);
复制代码

1.6 复杂的背景图案


前面咱们举了各类简单的例子,接下来咱们尝试下稍微复杂点的状况。

网格

background-image:linear-gradient(white 1px, transparent 0),
  linear-gradient(90deg, white 1px, transparent 0);
background-size: 30px 30px;
复制代码

咱们甚至能够把两幅不一样线宽、不一样颜色的网格图案叠加起来,获得一个更加逼真的蓝图网格。

background-image: linear-gradient(white 2px, transparent 0),
  linear-gradient(90deg, white 2px, transparent 0),
  linear-gradient(hsla(0,0%,100%,.3) 1px,transparent 0),
  linear-gradient(90deg, hsla(0,0%,100%,.3) 1px,transparent 0);
background-size: 75px 75px, 75px 75px,15px 15px, 15px 15px;
复制代码

波点

background: #655;
background-image: radial-gradient(tan 30%, transparent 0);
background-size: 30px 30px;
复制代码

background: #655;
background-image: radial-gradient(tan 30%, transparent 0),
  radial-gradient(tan 30%,   transparent 0);
background-size: 30px 30px;
background-position: 0 0, 15px 15px;
复制代码

棋盘

background-image: linear-gradient(45deg,rgba(0,0,0,.25) 25%, transparent 0,transparent 75%, rgba(0,0,0,.25) 0),
  linear-gradient(45deg,rgba(0,0,0,.25) 25%, transparent 0,transparent 75%, rgba(0,0,0,.25) 0);
background-position: 0 0, 15px 15px;
background-size: 30px 30px;
复制代码

波点, 棋盘最主要利用了偏移,使用 background-position来偏移第二个渐变,使用交差的方式,实现。

伪随机背景

天然界中,由于没有规律而美,而平时咱们使用渐变老是能查到必定的规律,那如何增长随机性?

background-image:
      linear-gradient(90deg, #fb3 11px, transparent 0),
      linear-gradient(90deg, #ab4 23px, transparent 0),
      linear-gradient(90deg, #655 41px, transparent 0);
background-size: 41px 100%, 61px 100%, 83px 100%;
复制代码

这个组合图案中第一个贴片的终点,就是各层背景图像以不一样间距重复数次后再次统一对齐的 点像这种,看起来并无遵循必定的规律,而这种是如何实现的?代码段中, background-size分别为 41, 61, 83若是细心的同窗可能会注意到它们都为 质数,由于咱们须要随机性更加真实,咱们得把贴片的尺寸最大化, 为了让最小公倍数最大化,这些数字最好是“相对质数” 平铺贴片的尺寸如今是 41×61×83=207 583 像素,比任何咱们所 能想像出的屏幕分辨率都要大!

请注意这个方法不只适用于背景,还能够用于其余涉及有规律重复的状况。

在照片图库中,为每幅图片应用细微的伪随机旋转效果时,可使用多个 :nth-child(a) 选择符,且让 a 是质数。

若是要生成一个动画,并且想让它看起来不是按照明显的规律在循环时,咱们能够应用多个时长为质数的动画。

连续的图像边框

有时咱们想把一幅图案或图片应用为边框,而不是背景。可能会有人说使用border-image,它的原理基本上就是九宫格伸缩法:把图片切割成九块,而后把它们应用到 元素边框相应的边和角。可是咱们但愿出如今拐角出的图片区域是随着元素宽高和边框厚度的变化而变化的。用border-image是不可能作到的。

在前面,咱们使用了不少的渐变背景,那咱们能不能使用渐变来解决这个难题?

padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white) padding-box, // 注意点
  repeating-linear-gradient(-45deg, red 0, red 12.5%,
  transparent 0, transparent 25%,
  #58a 0, #58a 37.5%,
  transparent 0, transparent 50%) 0 / 5em 5em;
复制代码

须要注意的是, background第一个白色背景的 background-clip是在 padding-box上的,这样防止白色背景覆盖边框和第二个背景。

蚂蚁行军,当鼠标点击某个元素时,咱们能看到边框能"行走",这是如何实现的?

@keyframes ants { to { background-position: 100% } }

...
padding: 1em;
border: 1px solid transparent;
background:
  linear-gradient(white, white) padding-box,
  repeating-linear-gradient(-45deg,
  black 0, black 25%, white 0, white 50%
  ) 0 / .6em .6em;
animation: ants 12s linear infinite;
复制代码

卡卷

.voucher {
   width: 150px;
   height: 80px;
   line-height: 5;
   background: radial-gradient(circle at 100% 50%, transparent 9px, #fff 0) 0 0 / 100% 100% no-repeat;
   filter: drop-shadow(3px 3px 2px rgba(0,0,0,.2)); 
}
复制代码

三角形

...
width: 0;
height: 0;
border-width: 0 25px 40px 25px;
border-style: solid;
border-color: transparent transparent rgb(245, 129, 127) transparent;
复制代码

这是利用什么原理实现?

盒子有marginborderpaddingcontent,下左下右边框交界处出呈现平滑的斜线。

咱们能够利用这个特色, 经过设置不一样的上下左右边框宽度或者颜色能够获得小三角等。

调整宽度大小能够调节三角形形状。

利用这个特色,咱们来看看其余的形状

height:20px;
width:20px;
border-color: red blue yellow orange;
border-style:solid;
border-width:20px;
复制代码

感兴趣的同窗,能够利用这个特色,去捣鼓其余的形状,这里就再也不举例啦。

2. 形状

2.1 自适应的椭圆

场景:当咱们要实现一个根据内容区的大小,自动适应的椭圆。如:

当内容区宽高相等,则为圆形。

当内容区宽度大于高度,则为椭圆。

border-radius能够帮咱们实现这一点,可是若是咱们使用px单位的话,并不能达到咱们想要的效果。

而它能够接受另外一个单位值,%百分比值。

border-radius ,有一个不为人知的真相:它能够单独指定水平垂直半径,只要用一个斜杠( / )分隔这两个值便可。

<main class="wrapper">
    <div class="voucher">我是一个形状</div>
</main>

.voucher {
  border-radius: 50% / 50%;
  padding: 10px;
  background: orange;
}
复制代码

因为斜杠先后的两个值如今是一致的,因此能够简化为:

...
border-radius: 50%;
复制代码

到这里你们能发现,border-radius实际上是一个简写属性,在水平方向上,它能够接受4个值,垂直也是。这四个值分别从左上角开始以顺时针顺序应用到元素的拐角。说到这,咱们直接举两个例子来看看效果吧。

半椭圆

...
border-radius: 50% / 100% 100% 0 0;
background: orange;
复制代码

四分之一

...
border-radius: 100% 0 0 / 100% 0 0;
复制代码

2.2 平行四边形

平时四边形形状,相信也是很经常使用的UI设计。而如何只用一个元素实现?可能咱们脑子立马会想到一个skew()变形,这个想法是对的。可是,若是你不作一些处理的话,内容也会跟着倾斜。那如何使内容不变化呢?

.voucher {
  position: relative;
  padding: 10px;
  z-index: 0;
}
.voucher::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: -1;
  background: orange;
  transform: skew(-45deg);
}
复制代码

这一实例,巧用 伪元素,来实现咱们想要的效果。

2.3 菱形图片

菱形图片的制做,咱们大概能想出,使用两个元素,而后旋转剪切啥的来实现。而咱们是利用clip-path来实现咱们的功能。

注意 cli-path有兼容性问题,若是项目考虑到兼容低版本的,须要注意。

<main class="wrapper">
    <img src="https://cdn.renqilai.com/2020_05_27/11_58_26.png" alt="我失败了">
</main>

img {
  width: 100px;
  height: 100px;
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
  transition: 1s clip-path;
}
img:hover {
  clip-path: polygon(0 0, 100% 0,100% 100%, 0 100%);
}
复制代码

咱们不只作出了棱形,顺带还让它动起来,使得不会那么枯燥。

clip-path能够绘制各类各样的形状,不过绘制点比较麻烦,快捷绘制出形状点我

顺带的也给出一位牛人使用clip-path作出的各种好玩的东西点我

(文章将持续中。。。)

2.3 菱形图片


亲,分享不易额,喜欢的话必定别忘了点💖!!!

只关注不点💖的都是耍流氓,只收藏也不点💖的也同样是耍流氓。

相关文章
相关标签/搜索