来看看CSS Functions好不好恰 🍽

2,374 阅读9分钟

🍽

它,来了,它来了,它扛着品如的衣柜来了 👗 👠 👚 ! 它就是✨ CSS Functions✨ 相信函数大家再熟悉不过了,比较官方的解释:

函数是指一段可以直接被另一段程序或代码引用的程序或代码。也叫做子程序、(OOP中)方法。一个较大的程序一般应分为若干个程序块,每一个模块用来实现一个特定的功能。所有的高级语言中都有子程序这个概念,用子程序实现模块的功能。

还是先用js说事儿吧,来点阳间的例子:

function say() {
  console.log('balabala');
}
 
function info(name, age) {
  console.log(name + ' is ' + age + ' years old.');
}
  
function sum(a, b) {
  console.log(a + b);
}

某些编程语言带有内置函数,可避免重复造轮子。 而CSS(Cascading Style Sheets)作为层叠样式表,也拥有自己的函数。可将它们插入要放置值的位置,或者在某些情况下,将其插入另一个值声明,一些CSS函数甚至允许函数嵌套。 然而,与其他编程语言不同,我们本身无法在CSS中创建自己的函数,只是没有感情的搬运工,这种逻辑保留给了CSS选择器。

一、🥗 开胃菜

1. url( ) 🔗

.el {
  background: url(/images/image.jpg);
}

这个老朋友了,经常会用在链接图片资源的时候被搬出来,比如 background-image 。传入url地址,来链接资源,包括图像,字体,甚至其他样式表。 URL 可以使用 ‘ ’ 或 “ ” 包含,也可以直接书写;可以是绝对地址,也可以使用相对地址(相对地址相对于 CSS 样式表的 URL,而不是网页的 URL)。

📌 出于性能方面的考虑,最好限制通过 url() 加载内容(每个声明都是一个附加的HTTP请求)

2. attr( ) 🔗

此功能使我们可以进入HTML,获取属性的内容,并将其提供给CSS content属性。

🧪 此功能某些浏览器尚在开发中 attr() 理论上能用于所有的CSS属性但目前支持的仅有伪元素的 content 属性,其他的属性和高级特性目前是实验性的

常用于:

  1. 打印样式表,用于在文本后显示链接的URL。

  2. 显示无法加载的图像的替代描述。

  /* <div data-example="foo"> */
div {
  content: attr(data-example);
}

3. calc( )🔗

这个函数有两个参数,并根据提供的运算符计算结果,可带单位也可不带。 与CSS预处理器(例如Sass)不同, calc() 可以混合单位,例如可执行 6rem - 100%calc() 也会动态更新。如果 100% 表示width,会随着width的变化动态更新。 calc() 还可以接受CSS自定义属性作为参数。

.el {
  width: calc(100vw - 80px);
}

🥐 MORE

A Complete Guide to calc() in CSS | CSS-Tricks

- 基本使用

有 / 无 单位均可,甚至可以没啥意义的 width: calc(20px)

🀄️

.el {
  font-size: calc(3vw + 2px);
  width:     calc(100% - 20px);
  height:    calc(100vh - 20px);
  padding:   calc(1vw + 5px);
}

/************************ As a part of a property ************************/
.el {
  margin: 10px calc(2vw + 5px);
  border-radius: 15px calc(15px / 3) 4px 2px;
  transition: transform calc(1s - 120ms);
}

/***** As a part of another function that forms a part of a property ******/
.el {
  background: #1E88E5 linear-gradient(
    to bottom,
    #1E88E5,
    #1E88E5 calc(50% - 10px),
    #3949AB calc(50% + 10px),
    #3949AB
  );
}

/********** calc( ) is for lengths and other numeric things ************/
.el {
  /* Nope! */
  counter-reset: calc("My " + "counter");
}
.el::before {
  /* Nope! */
  content: calc("Candyman " * 3);
}

/************************** 不要在media中使用 **************************/
@media (max-width: 40rem) {
  /* Narrower or exactly 40rem */
}
/* Nope! */
@media (min-width: calc(40rem + 1px)) {
  /* Wider than 40rem */
}
- 混合单位
- 预处理来battle
- Show the math
- calc( ) 中的操作符 + - * /
  - `+` `-` 都需要长度数值 
.el {
  margin: calc(10px + 10px);   /* 👍 */

  margin: calc(10px + 5);   /* 👎 */
}
  - `/` 要求第二个数是数字 
.el {
  margin: calc(30px / 3);    /* 👍 */

  margin: calc(30px / 10px);  /* 👎 */

  margin: calc(30px / 0);  /* 👎 0不能做除数 */
}
  - `*` 至少一个操作数是数字 
.el {
  margin: calc(10px * 3);  /* 👍 */
  
  margin: calc(3 * 10px);  /* 👍 */

  margin: calc(30px * 3px);  /* 👎 */
}
  - 空格有影响 ( `+``-`
.el {
  font-size: calc(3vw + 2px);  /* 👍 */

  font-size: calc(3vw+2px);  /* 👎 */

  font-size: calc(3vw - 2px);  /* 👍 */
  
  font-size: calc(3vw-2px);  /* 👎 */
}

负号是可以滴 (比如 calc(5vw - -5px) ),从这个例子里也可以看出来“空格”的作用 。 +- 如果没有空格, 2px-3px 会被解析为:数字 “2” 和 “px-3px”。 */ 操作符前后不需要空格,不过建议都整上吧 。

- 嵌套 calc(calc( ))

套娃可以但没必要 🕶️ 会把被嵌套的 calc() 函数全当成普通的括号

.el {
  width: calc(
    calc(100% / 3)
    -
    calc(1rem * 2)
  );
}

/* 和下面的一样 */
.el {
  width: calc(
   (100% / 3)
    -
   (1rem * 2)
  );
}

/* 根据操作符的优先级,还可以简化: */
.el {
  width: calc(100% / 3 - 1rem * 2);
}
- CSS 自定义属性 和 calc()
html {
  --spacing: 10px;
}
.module {
  padding: calc(var(--spacing) * 2);
}
  - 自定义属性可以相互引用 

但需要额外记忆,还会牺牲一定的可读性

html {
  --spacing: 10px;
  --spacing-L: var(--spacing) * 2;
  --spacing-XL: var(--spacing) * 3;
}
.module[data-spacing="XL"] {
  padding: calc(var(--spacing-XL));
}
  - 自定义属性可能来自HTML 
<div style="--index: 1;"> ... </div>
<div style="--index: 2;"> ... </div>
<div style="--index: 3;"> ... </div>
div {
  /* Index value comes from the HTML (with a fallback) */
  animation-delay: calc(var(--index, 1) * 0.2s);
}
  - 在后方添加单位 

一般当存储无单位数字,或者用无单位数字进行运算时,可和数值为1的单位相乘。

html {
  --importantNumber: 2;
}
.el {
  /* Number stays 2, but it has a unit now */
  padding: calc(var(--importantNumber) * 1rem);
}
  - 和颜色混用 
html {
  --H: 100;
  --S: 100%;
  --L: 50%;
}
.el {
  background: hsl(
    calc(var(--H) + 20),
    calc(var(--S) - 10%),
    calc(var(--L) + 30%)
  )
}
- 🌍Browser Tooling

4. :lang( ) 🔗

lang 在html元素上最常见,该声明可以传播到页面上的所有内容。 <html lang="en"> 告诉浏览器页面上的所有内容都是英语。 在HTML中, lang() 可用于根据属性值的存在与否,有条件地应用样式。 该选择器的一种常见用法:设置特定于语言的引号,这对于诸如国际化之类的事情非常有用。 机智的设计者和开发者可能会把它作为一个hook,为不同翻译版本的网页定制不同样式,尊重文化差异。

<div class="example">
    <p>
      In this example, the quotation marks for each quote are generated by the <code>lang</code> attribute applied to each quote's wrapping <code>p</code> element:
    </p>
    <div class="example__demo example__demo--lang">
          <p lang="en">
              <q>English quote</q>
          </p>
          <p lang="fr">
              <q>French quote</q>
          </p>
          <p lang="ko">
              <q>Korean quote</q>
          </p>
    </div>
</div>
   .example__demo--lang {
  font-size: var(--size-epsilon);
  
  // English
  p:lang(en) {
    color: var(--color-jaffa);
    quotes: "\201C" "\201D" "\2018" "\2019" "\201C" "\201D" "\2018" "\2019";
  }

  // French
  p:lang(fr) {
    color: var(--color-hibiscus);
    quotes: "\00AB" "\00BB" "\201C" "\201D" "\00AB" "\00BB" "\201C" "\201D";
  }

  // Korean
  p:lang(ko) {
    color: var(--color-fern);
    quotes: "\300C" "\300D" "\300E" "\300F" "\300C" "\300D" "\300E" "\300F";
  }
}

5. :not( ) 🔗

该伪类选择器将选择非指定选择器的元素。比如 body:not(img) 可以制定body中所有非图片的内容。目前 :not( ) 仅支持一个选择器参数,不过可以通过 , 作为分隔符,传入多个选择器。比如 div:not(.this, .that)

h3:not(:first-child) {
  margin-top: 0;
} 

二、🦞 主菜

1. CSS 自定义属性var( ) 🔗

2. 颜色

3. 伪类选择器

4. 动画

1. Animation-timing-function 🔗

随着时间的流逝来控制事物的状态。允许将动画或者过渡分割成段,而不是从一种状态持续到另一种状态的过渡。animation默认以ease方式过渡,它会在每个关键帧之间插入补间动画,所以动画效果是连贯性的。

  1. cubic-bezier( ) 

[cubic-bezier(.17,.67,.83,.67) ✿ cubic-bezier.com](https://cubic-bezier.com/#.17,.67,.83,.67) 

.el {
  transition-timing-function: 
    cubic-bezier(0.17, 0.67, 0.83, 0.67);
}
  2. steps( ) 

除了ease,linear、cubic-bezier之类的过渡函数都会为其插入补间。但有些效果不需要补间,只需要关键帧之间的跳跃,这时应该使用steps过渡方式(steps()就代替速度类型)。

steps 函数指定了一个阶跃函数 第一个参数指定了时间函数中的间隔数量(必须是正整数) 第二个参数可选,接受 start 和 end 两个值,指定在每个间隔的起点或是终点发生阶跃变化,默认为 end。 step-start等同于steps(1,start),动画分成1步,动画执行时为开始左侧端点的部分为开始; step-end等同于steps(1,end):动画分成一步,动画执行时以结尾端点为开始,默认值为end。

.el {
  animation: 2s infinite alternate steps(10);
}

2. path( )

主要跟SVG相关吧 🤔codepen

.clip-me {
  clip-path: path('M0.5,1 C0.5,1,0,0.7,0,0.3 A0.25,0.25,1,1,1,0.5,0.3 A0.25,0.25,1,1,1,1,0.3 C1,0.7,0.5,1,0.5,1 Z');
}
.move-me {
  offset-path: path("M56.06,227 ...");
}

🥐 MORE:Michelle Barker: CSS { In Real Life } | Fun with CSS Motion Path Dan Wilson : Get Moving (or not) with CSS Motion Path

5. 调整大小和缩放(转换) 🔗

要和 transform 一起用。 感受一下 📺 CSS Transform

1. scaleX( ), scaleY( ), scaleZ( ), scale3d( ), and scale( )

.double {
  transform: scale(2);
}

缩放:沿一个或多个轴增加或减小某物的大小。 scale3d() 可应用于三维空间。

2. translateX( ),translateY( ),translateZ( ),translate3d( ),和translate( )

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

位移:沿一个或多个轴重新定位元素。

3. perspective( )

.cube {
  transform: perspective(50em) rotateY(50deg)
}

透视:调整对象的外观,使其看起来像是从背景中向上突出或向外突出。

4. rotateX( ),rotateY( ),rotateZ( ),rotate3d( ),和rotate( )

.avatar {
  transform: rotate(25deg);
}

旋转:沿一个或多个轴旋转元素

5. skewX( ),skewY( )和skew( )

.header {
  transform: skew(25deg, 15deg);
}

偏斜函数与缩放和旋转函数有些不同,因为它们会相对于单个点施加变形效果。变形量与声明的角度和距离成比例,这意味着效果在一个方向上持续的越远,效果越明显。

6. 梯度函数 🔗

主要和颜色渐变有关吧

1. linear-gradient( ) 和 repeating-linear-gradient( )

.gradient {
  background-image: linear-gradient(315deg, #fde7f9 0%, #aacaef 74%);
}

.repeat-linear-gradient {
  background: repeating-linear-gradient(45deg, #fde7f9, #aacaef 10%);
 }

2. radial-gradient( ) 和 repeating-radial-gradient( ) (眩晕预警😨)

.radial-gradient {
  background: radial-gradient(ellipse at center,  rgba(255,130,0,1) 0%,rgba(249,0,112,1) 100%);
  border-radius: 250px;
  height: 250px;
  width: 250px;
}

background: repeating-radial-gradient(ellipse farthest-corner, rgba(255,130,0,1), rgba(249,0,112, 1) 25%);

3. conic-gradient( ) and repeating-conical-gradient( )

圆锥渐变与径向渐变的不同之处在于颜色绕圆旋转。

🎓 Background Patterns, Simplified by Conic Gradients | CSS-Tricks

实现一个棋盘格

.box {
  width: 200px;
  height: 200px;
  border: 1px solid black;
  background: conic-gradient(white 0 25%, black 0 50%, white 0 75%, black 0 100%);
}

7. Grid 🔗

三、🍰 甜点

滤镜 🔗

只能和 filter 一起使用。滤镜是应用于元素的特殊效果,模仿了诸如Photoshop之类的图形编辑程序的功能。

  • drop-shadow( ) 🔗

阴影是应用于对象的视觉效果,使它看起来像是在页面上悬停一样,可将阴影效果应用于文本和元素。与box-shadow属性的区别:它将阴影应用于元素的形状,而不是元素的实际盒子。

.fire {
  filter: drop-shadow(30px 10px 4px #4444dd);
}

  • 其他
/* URL to SVG filter */
filter: url("filters.svg#filter-id");

/* <filter-function> values */
filter: blur(5px);
filter: brightness(0.4);
filter: contrast(200%);
filter: drop-shadow(16px 16px 20px blue);
filter: grayscale(50%);
filter: hue-rotate(90deg);
filter: invert(75%);
filter: opacity(25%);
filter: saturate(30%);
filter: sepia(60%);

/* Multiple filters */
filter: contrast(175%) brightness(3%);

/* Use no filter */
filter: none;

/* Global values */
filter: inherit;
filter: initial;
filter: unset;

参考:

A Complete Guide to CSS Functions | CSS-Tricks

CSS(层叠样式表) | MDN

A Complete Guide to calc() in CSS | CSS-Tricks