CSS基础---了解CSS2.1以后的知识(5)

173 阅读32分钟

十三、丝滑的用户体验

(1)滚动相关

==> 平滑滚动 scroll-behavior <==

语法:

/* smooth:常用的属性值,可以让容器的滚动变得平滑 */
scroll-behavior: auto | smooth

举例: focus锚点定位选项卡切换技术

/* 主要CSS代码 */
.box {
    width: 20em;
    height: 10em;
    border: 1px solid #ddd;
    overflow: hidden;
    /* 让切换变得更加丝滑 */
    scroll-behavior: smooth;
}

.list {
    height: 100%;
    background: #ddd;
    text-align: center;
    position: relative;
}

.list > input {
    position: absolute;
    top: 0;
    height: 100%;
    width: 1px;
    border: 0;
    padding: 0;
    margin: 0;
    clip: rect(0 0 0 0);
}
<div class="box">
    <div class="list"><input id="one" readonly />1</div>
    <div class="list"><input id="two" readonly />2</div>
    <div class="list"><input id="three" readonly />3</div>
    <div class="list"><input id="four" readonly />4</div>
</div>

<div class="link">
    <label class="click" for="one">1</label>
    <label class="click" for="two">2</label>
    <label class="click" for="three">3</label>
    <label class="click" for="four">4</label>
</div>

image.png

注意: 凡是需要滚动的地方都可以加一句scroll-behavior:smooth,所以CSS在重置的时候可以像下面这样写

html,
body {
    scroll-behavior: smooth;
}

==> 停止滚动 overscroll-behavior <==

场景: 在默认情况下,局部滚动的滚动条滚动到底部边缘再继续滚动的时候,外部容器滚动条会继续跟着滚动。但是,有时候希望局部滚动的滚动条滚动到底部之后,滚动行为就停止。例如下拉列表框中的滚动条滚动到底部的时候,如果外部容器的滚动条还继续滚动,可 能就会把列表带走,这是不好的用户体验,此时就可以使用overscroll-behavior属性实现滚动停止

作用: 这个属性可以设置DOM元素滚动到边缘时的行为

语法:

overscroll-behavior: [ contain | none | auto ]{1,2}
  • auto: 默认值,表现为默认看到的滚动行为,即滚动条滚动到边缘后继续滚动外部的可滚动容器

  • contain: 默认的滚动溢出行为只会表现在当前元素的内部(例如“反弹”效果或刷新),不会对相邻的滚动区域进行滚动。例如浮层滚动(带弹性效果)时,底层元素不会滚动

  • none: 相邻的滚动区域不会发生滚动,并且会阻止默认的滚动溢出行为,与contain关键字的差异在于移动端

举例:

css-scroll {
    display: block;
    width: 280px;
    height: 200px;
    padding: 0.5em 1em;
    margin: 5em auto;
    border: solid deepskyblue;
    overflow: auto;
    /* 就这一句会发现在css-scroll这个元素中不管怎么动,外面的滚动条是纹丝不动的 */
    overscroll-behavior: contain;
    -ms-scroll-chaining: contain;
}
<css-scroll>
    <p>很多内容!!!!!!!!!!!!!!!</p>
    <p>很多内容!!!!!!!!!!!!!!!</p>
    <p>很多内容!!!!!!!!!!!!!!!</p>
    <p>很多内容!!!!!!!!!!!!!!!</p>
    <p>很多内容!!!!!!!!!!!!!!!</p>
    <p>很多内容!!!!!!!!!!!!!!!</p>
    <p>很多内容!!!!!!!!!!!!!!!</p>
    <p>很多内容!!!!!!!!!!!!!!!</p>
    <p>很多内容!!!!!!!!!!!!!!!</p>
    <p>很多内容!!!!!!!!!!!!!!!</p>
    <p>很多内容!!!!!!!!!!!!!!!</p>
    <p>很多内容!!!!!!!!!!!!!!!</p>
</css-scroll>

image.png

注意: 这个属性也支持分解为overscroll-behavior-x和overscroll-behavior-y两个独立的CSS属性,分别表示水平滚动和垂直滚动的边界行为

==> 滚动锚定 overflow-anchor <==

滚动锚定: 在浏览图片网站的时候,如果上方的图片加载很慢,当你正在看下面的图片的时候,上面的图片加载好了,此时你所看的那张图片就会往下跑,这样又需要自己去寻找这张图片的位置,这是不友好的体验,于是Chrome和Firefox浏览器实现一种滚动锚定的交互行为,具体表现为当前视口上面的内容突然出现的时候,浏览器会自动改变滚动 高度,让视口区域内容固定,就像滚动效果被锚定一样,因此在这两个浏览器中阅读文章或者看漫画的时候,是感觉不到页面跳动的,这就是滚动锚定在起作用

语法:

overflow-anchor: auto | none
  • auto:是初始声明,表示浏览器自己决定滚动锚定的行为,通常表现为执行滚动锚定

  • none:则表示禁止滚动锚定的行为

说明: 有时候浏览器觉得正确的事情对于用户来说不一定正确,比如在浏览网页的时候,滑动到底部会自动加载一些数据,有时候是想先看到这些加载的数据的,此时滚动锚定就拖后腿了,此时就需要overflow-anchor来取消这个行为,看下面这个例子就明白了

<div class="on" id="on">
    <h2>overflow-anchor: auto;</h2>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
</div>

<div class="off" id="off">
    <h2>overflow-anchor: none;</h2>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
    <p>很多内容</p>
</div>
.on {
    overflow-anchor: auto;
}

.off {
    overflow-anchor: none;
}

div {
    width: 320px;
    max-width: 100%;
    height: 400px;
    overflow-x: hidden;
}

.thing {
    height: 100px;
    background: green;
    display: grid;
    place-items: center;
    color: white;
}

.thing::before {
    content: "临时插入内容";
}
var addBox = function (event) {
    var target = event.target;
    setTimeout(function () {
        var newNode = document.createElement("div");
        newNode.classList.add("thing");
        var p = target.querySelector("p");
        target.insertBefore(newNode, p);
        target.removeEventListener("scroll", addBox, false);
    }, 1000);
};

document.getElementById("on").addEventListener("scroll", addBox, false);
document.getElementById("off").addEventListener("scroll", addBox, false);

image.png

==> 了解 CSS Scroll Snap <==

说明: 这是一个独立的模块,可以让网页容器滚动停止的时候,自动平滑定位到指定元素的指定位置,包含以scroll-和scroll-snap-开头的诸多CSS属性

<== 举例了解 ==>

.scroll-x {
    max-width: 414px;
    height: 420px;
    margin: auto;
    scroll-snap-type: x mandatory;
    white-space: nowrap;
    overflow: auto;
}

.scroll-x img {
    width: 300px;
    height: 400px;
    scroll-snap-align: center;
}
<div class="scroll-x">
    <img src="D:1.jpg" />
    <img src="D:1.jpg" />
    <img src="D:1.jpg" />
    <img src="D:1.jpg" />
</div>

image.png

效果: 在水平移动滚动条的时候会发现中间的照片不管移动到什么地方都会让其居中展示,这就是CSS Scroll Snap的作用,可以让页面滚动停留在你希望用户关注的重点区域

注意: 实现这个效果需要容器使用scroll-snap-type属性,子元素使用scroll snap-align属性

<== 相关CSS属性 ==>

作用在滚动容器上作用在滚动定位子元素上
scroll-snap-typescroll-snap-align
scroll-snap-stopscroll-margin/scroll-margin-*
scroll-padding/scroll-padding-*

说明: 作用在容器上的scroll-padding相关属性和作用在子元素上的scroll-margin相关属性都是用来调整定位点的位置的,与定位效果没有必然关系,且语法上与padding和margin属性一致,因此只需要关注剩下的三个属性就好了

<== scroll-snap-type 属性 ==>

作用: 确定定位方式是水平滚动定位,还是垂直滚动定位。它支持的属性值有以下几个

  • none: 默认值,表示滚动时忽略捕捉点,也就是平时使用滚动

  • x: 捕捉水平定位点

  • y: 捕捉垂直平定位点

  • block: 捕捉和块状元素排列一个滚动方向的定位点,默认文档流下指的就是垂直轴

  • inline: 捕捉和内联元素排列一个滚动方向的定位点,默认文档流下指的就是水平轴

  • both: 横轴、纵轴都捕捉

  • mandatory: 表示强制,为可选参数。强制定位,也就是如果存在有效的定位点位置,则滚动容器必须在滚动结束时进行定位

  • proximity: 表示大约,为可选参数。可能会定位,这个值的作用表现为让浏览器自己判断要不要定位

注意: 大多数时候,参数mandatory和proximity的效果是类似的,只有在滚动容器的窗口尺寸比子元素的尺寸还要小的时候,参数 mandatory和proximity的差异才会体现出来

.scroll {
    overflow: auto;
}

.scroll-y {
    max-width: 300px;
    height: 150px;
}

.mandatory {
    scroll-snap-type: y mandatory;
}

.proximity {
    scroll-snap-type: y proximity;
}

.scroll img {
    scroll-snap-align: center;
}
<section>
    <h4>垂直滚动 - mandatory</h4>
    <div class="scroll scroll-y mandatory">
        <img src="D:1.jpg" />
        <img src="D:1.jpg" />
        <img src="D:1.jpg" />
        <img src="D:1.jpg" />
    </div>
</section>

<section>
    <h4>垂直滚动 - proximity</h4>
    <div class="scroll scroll-y proximity">
        <img src="D:1.jpg" />
        <img src="D:1.jpg" />
        <img src="D:1.jpg" />
        <img src="D:1.jpg" />
    </div>
</section>

image.png

解释: 这样设计是为了让滚动容器在尺寸不足的时候,不会出现部分区域或部分元素永远不可见的情况。比如在上面的例子中使用mandatory定位的图片靠近上下边缘的区域是永远看不到的,但是使用proximity定位的图片却不是这样

推荐使用: 在绝大多数场景下,都是使用mandatory属性值进行强制定位,但是,如果容器尺寸较小,有部分重要内容必须要显示,则使用proximity属性值进行非强制定位

<== scroll-snap-stop 属性 ==>

作用: 表示是否允许滚动容器忽略捕获位置,可以保证每次只滚动一屏或一个指定元素,而不会一下子滚动多屏或多个元素

语法:

scroll-snap-stop: normal | always
  • normal:默认值,可以忽略捕获位置

  • always:不能忽略捕获位置,且必须定位到第一个捕获元素的位置

<== scroll-snap-align 属性 ==>

作用: 在滚动容器子元素上的,表示捕获点是上边缘、下边缘或中间位置。它支持的属性值有以下几个

  • none: 默认值,不定义位置

  • start: 起始位置对齐,如垂直滚动、子元素和容器同上边缘对齐

  • end: 结束位置对齐,如垂直滚动、子元素和容器同下边缘对齐

  • center: 居中对齐,子元素中心和滚动容器中心一致

注意: 这个属性支持同时使用两个属性值

scroll-snap-align: start end;

==> 自定义滚动条 CSS Scrollbars <==

说明: 由于滚动条样式进行自定义的需求比较常见,因此就形成了CSS Scrollbars模块规范的草案,其中包括了scrollbar-width和scrollbar-color这两个CSS属性

<== scrollbar-width 属性 ==>

作用: 用来设置滚动条的宽度,仅支持关键字属性值,并不支持具体的长度值

语法:

scrollbar-width: auto | thin | none;
  • auto:采用系统默认的滚动条样式

  • thin:如果系统有窄的滚动条选项就使用这个窄的滚动条,如果没有就使用比系统默认滚动条宽度窄一点的宽度

  • none:滚动条不显示,但是页面还是可以正常滚动

<== scrollbar-color 属性 ==>

作用: 用来设置滚动条的颜色

语法:

scrollbar-width: auto | dark | light | <color>{2};
  • auto: 采用系统默认的滚动条颜色,具体的颜色值由操作系统使用的主题决定

  • dark: 显示为深色滚动条,它可以是系统提供的滚动条的深色变体,也可以是带有深色的自定义滚动条

  • light:显示为浅色滚动条,它可以是系统提供的滚动条的浅色变体,也可以是带有浅色的自定义滚动条

  • <color> :专门指定滚动条的颜色,其中第一个颜色值表示点击滑块的颜色,对应webkit内核浏览器私有的::-webkit-scrollbar-thumb伪元素,第二个颜色值表示滚动轨道的颜色,对应webkit内核浏览器私有的::-webkit-scrollbar-track伪元素

举例:

.scroll {
    border: 1px solid #665;
    width: 300px;
    height: 100px;
    overflow: auto;
    --thumb-color: #bbb;
    --track-color: #ddd;
}

.scroll-thin {
    scrollbar-width: thin;
    scrollbar-color: var(--thumb-color) var(--track-color);
}

.scroll-none {
    /* Firefox浏览器标准CSS属性自定义,让滚动条消失 */
    scrollbar-width: none;
}

.scroll-thin::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

.scroll-thin::-webkit-scrollbar-thumb {
    background-color: var(--thumb-color);
}

.scroll-thin::-webkit-scrollbar-track {
    background-color: var(--track-color);
}

/* Chrome浏览器私有方法隐藏滚动条 */
.scroll-none::-webkit-scrollbar {
    width: 0;
    height: 0;
}
<h4 class="fill">窄滚动条</h4>
<div class="scroll scroll-thin">
    <p>根据测试,窄滚动条在Windows操作系统中占据的宽度是8px。</p>
    <p>测试方法很简单,滚动容器的宽度减去子元素的宽度即可。</p>
    <p>
        打开控制台,审查对应的元素,就可以看到容器的宽度和子元素的宽度,两者相互减,就是滚动条的宽度了。
    </p>
</div>

<h4 class="fill">无滚动条-可滚动</h4>
<div class="scroll scroll-none">
    <p>根据测试,窄滚动条在Windows操作系统中占据的宽度是8px。</p>
    <p>测试方法很简单,滚动容器的宽度减去子元素的宽度即可。</p>
    <p>
        打开控制台,审查对应的元素,就可以看到容器的宽度和子元素的宽度,两者相互减,就是滚动条的宽度了。
    </p>
</div>

image.png

(2)点击行为

==> pointer-events:none <==

<== 不要用来禁用按钮 ==>

说明: 由于这个声明可以让元素无视点击、鼠标悬停和拖拽等行为,从而你可以会将其用在按钮的上来实现禁用效果,但这是不推荐的写法,原因如下

button.disabled { 
    opacity: .4;
    pointer-events: none;
}
  • pointer-events:none并不能阻止键盘行为,按钮元素依然可以通过Tab键被focus聚焦,并且可以在focus聚焦状态下通过Enter键触发点击事件,也就是设置pointer-events: none声明实现的禁用效果只是部分禁用,并不是真正意义上的禁用

  • pointer-events:none影响无障碍访问,例如,在按钮被禁用的时候,可以通过title属性或其他提示组件在鼠标指针悬停在按钮上时显示禁用的原因,如果设置了pointer-events:none,则无法显示这些提示效果。移动端的无障碍阅读是通过触摸触发的,如果设置了pointer-events:none,就会影响识别

解决: 使用按钮原生的disabled属性,然后配合:disabled伪类实现

<button disabled>
    按钮
</button>
button:disabled {
    opacity: .4;
}

<== 继承性 ==>

特点: 子元素的pointer-events属性值可以覆盖祖先元素的pointer-events属性值

场景举例: 如果需要点击黑色半透明覆盖层依然可以选中下层的元素该怎么做

<!-- <dialog>包含覆盖整个屏幕的半透明黑色覆盖层 -->
<dialog>
    <!-- .container元素是弹框主体元素 -->
    <div class="container">中间的弹框主体</div>
</dialog>
dialog {
    pointer-events: none;
}

.container {
    pointer-events: auto;
}

<== 语法 ==>

说明: 除了auto和none这两个关键字属性值,其他值都是作用在SVG元素上的

pointer-events: auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all;
  • visiblePainted: SVG元素响应鼠标事件首先需要visibility的计算值是visible,同时鼠标指针移动到填充区域的时候fill不是none,移动到描边区域的时候stroke不是none。换句话说,肉眼可见的有描边或有填充的地方都可以响应鼠标事件

  • visibleFill: SVG元素响应鼠标事件首先需要visibility的计算值是visible,同时鼠标指针经过的区域需要是填充区域,无论有没有填充颜色或图案都可以响应,但是同时会忽略描边区域。换句话说,鼠标指针经过SVG元素的描边区域不会有任何鼠标响应事件发生

  • visibleStroke: 和visibleFill关键字属性值的区别就是描边和填充的地位调换了。对于属性值visibleStroke,鼠标指针经过描边区域可以影响鼠标事件,但是经过填充区域不会有任何响应

  • visible: SVG元素只需要visibility的计算值是visible就能影响点击事件,不管fill属性值是不是none,也不管stroke属性值是不是none。换句话说,只要元素显示,任意描边或填充区域都可以响应鼠标事件

  • painted: 和visiblePainted关键字属性值的区别在于,对于painted属性值,就算元素的visibility计算值是hidden,也是可以影响鼠标事件的,例如点击或者悬停效果 等

  • fill: 类似的,fill关键字并不需要SVG元素的visibility计算值是visible,就算visibility计算值是hidden,鼠标一样可以点击填充区域

  • stroke: SVG元素的visibility计算值就算是hidden,描边区域也能响应鼠标事件,填充区域则不能响应鼠标事件

  • all:和painted关键字的区别在于,painted关键字需要 fill或者stroke的属性值不是none,而all关键字没有这个限制

(3)拉伸行为

==> resize 属性 <==

image.png

说明: 比如<textarea>元素,你会看见右下角存在一个特殊的记号,按住这个记号进行上下左右拉伸,会发现元素的高度和宽度会发生变化,这就是resize属性在起作用

语法:

resize: none | both | horizontal | vertical | block | inline;
  • none: 初始值,表示没有拉伸效果,常用来重置元素内置的拉伸行为

  • both: 既可以水平方向拉伸,也可以垂直方向拉伸

  • horizontal: 仅可以水平方向拉伸,此时鼠标的指针也会变成水平方向的拉伸样式

  • vertical: 仅可以垂直方向拉伸,此时鼠标的指针也会变成垂直方向的拉伸样式

  • block: 后期新增的属性值,目前现代浏览器都提供支持。其表示沿着块级元素的排列方向拉伸,默认是垂直方向,也可能是水平方向,这取决于writing-mode的值

  • inline: 和block属性值类似,只是inline表示内联元素的排列方向。默认是水平方向,如果使用writing-mode属性改成垂直排版,则inline的拉伸方向就会变成垂直方向

<== 生效条件 ==>

限制条件:

  • 不支持内联元素

  • 如果是块级元素,需要overflow属性的计算值不是visible

div {
    width: 100px;
    height: 100px;
    border: 1px solid red;
    overflow: hidden;
    resize: both;
}

image.png

<== 原理 ==>

说明: 通过设置元素的width属性值和height属性值实现的,因此,如果希望元素拉伸的尺寸不是无限的,可以通过设置min-width、min-height、max-width和max-height这些CSS属性值进行限制

image.png

注意: resize属性的拖拽条和滚动条是同源的,也就是在自定义滚动条尺寸的时候,resize属性拖拽条的尺寸也会跟着变化,其拖拽条的样式可以使用::-webkit-resizer伪元素进行自定义

(4)输入行为

==> cater-color 属性 <==

作用: 可以改变输入框插入光标的颜色,但不改变输入框里内容的颜色

input {
    color: #333;
    caret-color: red;
}

image.png

注意: 这个属性不仅对原生的输入表单控件有效,也适用于设置contenteditable的普通HTML标签

(5)选择行为

==> user-select 属性 <==

语法:

user-select: auto | text | none | contain | all
  • auto: 如果将父元素的user-select属性值设置为all,则当前元素的user-select属性值表现也是all。如果将父元素的user-select属性值设置为none,则当前元素的user-select属性值表现也是none;但这并不是user-select属性有继承性,而是auto的表现而已

  • text: 表示文字和图片可以被选中

  • contain: 表示元素可以被选中

  • all: 表示元素的内容需要整体选择

举例:

section {
    user-select: all;
}
<!-- 此时,<section>元素自身或<section>元素的任意文字内容 -->
<!-- (包括子元素中的文字内容)只要被点击(无论是鼠标左键还 --> 
<!-- 是右键点击),<section>元素里面所有图文内容都会被选中 -->
<section>111</section>

image.png

注意:

  • 无论将user-select属性值设为什么,::before 和::after伪元素生成的内容都表现为none,也就是生成的内容永远无法被选中

  • Safari浏览器一直需要添加-webkit-私有前缀,Firefox浏览器以69版本开始不需要再添加-moz-私有前缀,如果项目需要兼容IE浏览器,则需要添加-ms-私有前缀(IE10+支持)。因此,对于user-select属性,为了安全起见,所有私有前缀都可以加上

  • IE浏览器虽然不支持all值,但是支持非规范的element值,其含义和contain一样,可以用来选择元素

body {
    /* 兼容性写法 */
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

==> ::selection 伪元素 <==

说明: 这个伪元素可以改变文字被选中后的颜色和背景色

.maroon::selection {
    background: maroon;
    color: #fff;
}
<p class="maroon">这是一段文本</p>

image.png

注意: 这个伪元素不仅可以改变被选中文字的样式,被选中的图像的样式也是可以修改的

(6)打印行为

说明: 相比正常浏览的页面,打印页面的时候往往需要隐藏一些不需要的信息,例如隐藏头部和底部,只留中间的主体信息,这些需求都是通过媒体查询语句实现的;但是比如分页的时候希望内容不断开,打印的时候希望保留背景色等,这时就需要使用特别的CSS属性进行处理了,媒体查询是不管用的...

==> color-adjust 背景色 <==

作用: 用来设置打印页面的时候是否打印背景色

语法:

color-adjust: economy | exact;
  • economy: 默认值,表现为浏览器(或其他客户端)对元素进行样式上的调整,调整的规则由浏览器自己决定,以便达到更好的输出效果。例如,当打印时,浏览器会选择省略所有背景图像,并调整文本颜色,以确保对比度,保证白纸上的阅读效果是最佳的

  • exact: 告诉浏览器,我设置的这些颜色和背景等元素都是有必要的、精确匹配的,你不要自作聪明帮我做调整,也就是背景色啥的会被保留的

举例:

<h4 class="fill">color-adjust:economy(默认)</h4>
<table>
    <tr>
        <td>《CSS》</td>
        <td>2018年</td>
    </tr>
    <tr>
        <td>《CSS》</td>
        <td>2019年</td>
    </tr>
    <tr>
        <td>《CSS》</td>
        <td>2021年</td>
    </tr>
</table>

<h4 class="fill">color-adjust:exact</h4>
<table class="exact">
    <tr>
        <td>《CSS》</td>
        <td>2018年</td>
    </tr>
    <tr>
        <td>《CSS》</td>
        <td>2019年</td>
    </tr>
    <tr>
        <td>《CSS》</td>
        <td>2021年</td>
    </tr>
</table>
tr:nth-child(odd) td {
    background-color: #eee;
}

.exact {
    -webkit-print-color-adjust: exact;
    color-adjust: exact;
}

image.png

==> page-break 分页控制 <==

<== break-before/after ==>

作用: break-before属性的作用是让当前元素作为一栏或一页的起始元素,break-after的作用是让当前元素作为一栏或一页的末尾元素,它们的语法是一样的

语法:

break-before: auto | avoid | always | all | avoid-page | page | left | right | recto | verso | avoid-column | column | avoid-region | region;
break-after: auto | avoid | always | all | avoid-page | page | left | right | recto | verso | avoid-column | column | avoid-region | region;

分类:

作用场景可以使用的属性值
常规中断值auto、avoid、always、all
分页使用值avoid-page、page、left、right、 recto、verso
分栏使用值avoid-column、column
分区使用值avoid-region、region

说明: 这两个属性常用的只有column和page这两个属性值,它们的作用如下

  • column: 用在CSS分栏布局中,如果是break-before属性,则表示元素是分栏第一个元素;如果是break-after属性,则表示元素是分栏最后一个元素;如果存在分栏不够的情况,会重新创建一栏

  • page: 用在打印布局中,如果是break-before属性,则表示元素是分页第一个元素;如果是break-after属性,则表示元素是分页最后一个元素

举例:

image.png

image.png

十四、使用CSS绘制SVG元素

说明: 主要使用的是SVG元素的标签属性来作为CSS属性实现的

(1)使用CSS绘制SVG图形

==> 基础图形的绘制 <==

圆形:

<svg>
    <circle class="circle"></circle>
</svg>
.circle {
    /* cx:圆心X的坐标 */
    cx: 150px;
    /* cy:圆心y的坐标 */
    cy: 75px;
    /* r:圆的半径 */
    r: 60px;
}

image.png

圆角矩形:

.rect {
    x: 30px;
    y: 15px;
    width: 240px;
    height: 120px;
    /* rx:椭圆长半轴 */
    rx: 10px;
    /* ry:椭圆短半轴 */
    ry: 10px;
}
<svg>
    <rect class="rect"></rect>
</svg>

image.png

椭圆:

.ellipse {
    cx: 150px;
    cy: 75px;
    rx: 100px;
    ry: 60px;
}
<svg>
    <ellipse class="ellipse"></ellipse>
</svg>

image.png

菱形:

.diamond { 
    /* d:路径 */
    d: path('M150 10L240 75L150 140L60 75'); 
}
<svg> 
    <path class="diamond"> 
</svg> 

image.png

==> 好处 <==

<== 增强了复用性 ==>

说明: 复用性是CSS属性有一个天然的优势,这个也很好理解,比如有10个一样的SVG原型效果,如果使用传统的SVG图标的话,那么就会像下面这样写,这样很明显可维护性很差,如果要把所有圆形的半径从60px改成75px,那么就需要修改10处地方,这会显得非常的麻烦,如果像上面那样使用一个类名进行管理的话,那么修改起来就十分的容易了

<svg>
    <circle cx="150" cy="75" r="60"></circle>
</svg>
<svg>
    <circle cx="150" cy="75" r="60"></circle>
</svg>
...

<== 可以通过外部手段重置SVG ==>

说明: 这个也很好理解,由于CSS选择器的优先级均大于HTML属性中的设置,因此所有SVG中通过属性设置的特性,只要有对应的CSS属性,均可以在CSS样式中进行重置

<== 可以实现SVG动画 ==>

说明: 这里同样是直接使用对应的CSS属性就可以完成

<svg>
    <circle cx="150" cy="75" r="60"></circle>
</svg>
circle {
    animation: zoomInOut 1s infinite alternate;
}

@keyframes zoomInOut {
    from {
        r: 60px;
    }
    to {
        r: 75px;
    }
}

image.png

(2)CSS属性下的SVG填充

==> fill 属性的基本使用 <==

说明: 这个属性可以设置SVG中元素的填充样式,它有着类似于继承性的样式表现

<!-- 也就是svg元素上设置填充色后,它的子元素都会继承这个填充色 -->
<svg fill="skyblue">
    <circle cx="150" cy="75" r="60"></circle>
    <rect x="30" y="45" width="240" height="60"></rect>
</svg>

image.png image.png

注意: 这个属性可以设置在任何的HTML元素上面,同样也存在继承的特性,这个特性成了SVG Sprites技术的理论基础之一

/* 此时在整个页面中,所有内联SVG元素都会使用当前的文字颜色作为 */
/* 填充颜色(前提是所有SVG元素都没有设置fill属性) */
body { 
    fill: currentColor;
}

举例:

<svg style="display:none;">
    <symbol id="icon-circle" viewBox="0 0 150 150"><circle cx="75" cy="75" r="60"></circle></symbol>
    <symbol id="icon-rect" viewBox="0 0 150 150"><rect x="10" y="25" width="130" height="100"></rect><symbol>
    <symbol id="icon-ellipse" viewBox="0 0 150 150"><ellipse cx="75" cy="75" rx="65" ry="50"></ellipse></symbol>
    <symbol id="icon-diamond" viewBox="0 0 150 150"><path d="M75 10L140 75L75 140L10 75"></symbol>
</svg>

<h4 class="fill">深红色</h4>
<p style="color: darkred;">
    <svg><use href="#icon-circle"></use></svg>圆形
    <svg><use href="#icon-rect"></use></svg>矩形
    <svg><use href="#icon-ellipse"></use></svg>椭圆
    <svg><use href="#icon-diamond"></use></svg>棱形
</p>

<h4 class="fill">绿色</h4>
<p style="color: green;">
    <svg><use href="#icon-circle"></use></svg>圆形
    <svg><use href="#icon-rect"></use></svg>矩形
    <svg><use href="#icon-ellipse"></use></svg>椭圆
    <svg><use href="#icon-diamond"></use></svg>棱形
</p>

<h4 class="fill">深天蓝色</h4>
<p style="color: deepskyblue;">
    <svg><use href="#icon-circle"></use></svg>圆形
    <svg><use href="#icon-rect"></use></svg>矩形
    <svg><use href="#icon-ellipse"></use></svg>椭圆
    <svg><use href="#icon-diamond"></use></svg>棱形
</p>
body {
    fill: currentColor;
}

p {
    font-size: 1.5rem;
}

svg {
    width: 1.25em; height: 1.25em;
    vertical-align: -.5ex;
}

image.png

==> 了解 fill-opacity 属性 <==

作用: 用来设置填充颜色或者填充图像的透明度

<svg style="position: absolute; left: -999px">
    <defs>
        <linearGradient id="myGradient">
            <stop offset="0%" stop-color="deeppink" />
            <stop offset="100%" stop-color="deepskyblue" />
        </linearGradient>
    </defs>
</svg>

<svg>
    <circle class="circle" cx="150" cy="75" r="60"></circle>
</svg>
.circle {
    fill: url(#myGradient);
    fill-opacity: 0.5;
}

image.png

注意: 这个效果在IE9浏览器中也是正常的,因此,如果项目需要兼容IE9浏览器,同时需要使用渐变效果(例如颜色选择组件),则可以使用SVG渐变,并使用fill属性进行填充,以及使用fill-opacity属性控制透明度;此外,这个属性也表现出了继承性

==> 了解 fill-rule 属性 <==

说明: 这个属性表示路径发生交叉时的填充规则,支持nonzero和evenodd这两个属性值,对于这两个属性值在上一篇的最后提到过

举例:

<svg viewBox="-10 -10 220 120">
    <polygon class="nonzero" points="50,0 21,90 98,35 2,35 79,90" />
    <polygon class="evenodd" points="150,0 121,90 198,35 102,35 179,90" />
</svg>
.nonzero {
    stroke: deepskyblue;
    fill-rule: nonzero;
}

.evenodd {
    stroke: deepskyblue;
    fill-rule: evenodd;
}

image.png

(3)CSS属性下的SVG描边

==> 兼容性很好的文字描边效果 <==

说明: text-stroke属性可以设置文字的描边效果,但是IE浏览器不支持这个属性,如果需要IE浏览器中的文字也有描边效果,可以使用SVG元素中的stroke和stroke-width属性,比如下面这个例子

注意: 由于SVG中的文本内容不会自动换行,因此,该技术更适合单行文字内容,或者是内容宽度固定的多行文字内容

svg {
    max-width: 100%;
    width: 500px;
    height: 100px;
}

text {
    font-size: 50px;
    font-weight: bold;
    fill: white;
    stroke: deepskyblue;
}

tspan {
    stroke: deeppink;
    stroke-width: 2px;
}
<!-- Chrome浏览器下 -->
<section>
    <p>感谢您使用<span>CSS</span></p>
</section>

<!-- 兼容IE的写法 -->
<svg>
    <!-- SVG中的text元素对应传统HTML标签中的p标签 -->
    <text y="70%">
        感谢您使用
        <!-- tspan对应span元素 -->
        <tspan>CSS</tspan>
    </text>
</svg>

image.png

了解: 这里还有几个可以控制描边细节的CSS属性,如下

  • stroke-linecap: 表示描边端点表现方式,可用属性值有butt(默认值)、round和square,这些属性值只有在非闭合路径中才能看到

  • stroke-linejoin: 表示描边转角的表现方式,可用值有miter(默认值)、round和bevel

  • stroke-miterlimit: 表示描边相交形成的锐角的表现方式,默认大小是4。锐角形成的间距小于4的位置表现为平角,不再显示为锐角。因此,stroke-miterlimit属性只有在stroke-linejoin属性值是miter的时候才有效,同时stroke-miterlimit的属性值越大,锐角的损耗就越大

  • stroke-opacity: 表示描边透明度,默认属性值是1,范围是0~1。尽量不要使用百分比值,因为IE浏览器和Edge浏览器并不支持

image.png

image.png

image.png

==> 可控的虚线效果 <==

说明: 在SVG中使用stroke-dasharray属性可以实现伸缩自如的虚线效果

举例: 实现一个长短相间的虚线框效果

<svg>
    <rect x="10" y="10" width="280" height="130"></rect>
</svg>
<svg>
    <circle cx="150" cy="75" r="60"></circle>
</svg>
rect,
circle {
    fill: none;
    stroke: deepskyblue;
    stroke-width: 4px;
    stroke-dasharray: 14px 4px 4px 4px;
}

image.png

语法: 就是实色长度、透明长度、实色长度、透明长度这样一直循环下去

stroke-dasharray:4px 1px 2px 4px 1px 2px 4px 1px 2px

image.png

==> stroke-dashoffset 属性的经典场景 <==

作用: 设置描边的起始偏移,如果偏移距离足够大,描边就会看不见;如果偏移为0,描边就会完整显示

<== SVG路径描边动画效果 ==>

说明: 这种动画可以让任意SVG图形以线条动画的方式出现,适合用在注重视觉表现的运营活动页面中

<svg width="700" height="350" viewBox="0 0 700 350">
    <path
        d="m106,93c3,0 4.31001,0.33749 7,2c3.60901,2.23049 6.71413,6.21168 9,9c0.89659,1.09367 3,2 3,3c0,1 -0.49345,1.87856 -1,5c-0.32036,1.97418 -0.96855,5.41208 -3,9c-0.69678,1.23065 -1,4 -1,8c0,3 0,4 0,7c0,2 0.69255,5.186 2,7c0.8269,1.14726 2,4 2,6c0,4 0,6 0,8c0,2 0,5 0,8c0,3 -1,7 -1,10c0,7 0,10 0,15c0,4 0.82443,6.09789 2,8c2.10292,3.4026 1.1731,5.85274 2,7c1.30745,1.814 1,3 1,5c0,2 0,4 0,6c0,2 -1.61731,5.07613 -2,6c-0.5412,1.30656 -3.87856,3.49345 -7,4c-2.96126,0.48055 -7,0 -12,0c-8,0 -13.16119,0.2536 -18,-3c-4.14924,-2.78995 -7.23296,-3.58972 -11,-6c-5.39359,-3.45099 -10.76291,-7.13878 -14,-16c-2.4263,-6.64177 -3.15977,-10.80232 0,-16c2.59731,-4.27246 9.891,-8.22313 22,-14c10.90556,-5.20274 26.49663,-12.73625 41,-16c19.60938,-4.41277 35.05527,-4.50844 55,-7c20.06776,-2.50693 37.9556,-7.13666 47,-10c9.9534,-3.15112 16.06985,-4.62152 19,-8c2.07193,-2.38896 2,-5 2,-8c0,-1 -0.71411,-3.21167 -3,-6c-0.89661,-1.09367 -1.38062,-4.44353 -7,-6c-1.92743,-0.53387 -7,-3 -14,-3c-3,0 -8,0 -10,0c-7,0 -9.38487,1.84787 -16,6c-3.49219,2.19194 -8.44798,5.44547 -15,13c-4.63298,5.34187 -6.69981,9.16617 -14,22c-2.88301,5.06836 -3.69255,10.186 -5,12c-0.8269,1.14726 -1.92386,3.61731 -1,4c1.30656,0.5412 2.18875,-1.41528 3,-2c2.56537,-1.84901 2.90283,-5.2242 5,-6c3.867,-1.4305 5.29289,-2.29289 6,-3c1.41422,-1.41422 3,1 4,2c4,4 7.21167,7.71413 10,10c12.03038,9.86255 15.76393,13.76393 18,16c2.23607,2.23607 2.82375,4.48625 5,5c0.97325,0.22975 1.4595,-1.0535 1,-3c-0.51375,-2.17625 -2,-6 -2,-13c0,-2 -1.14806,-3.22836 0,-6c0.5412,-1.30656 2,-1 3,-1l1,0l0,1l1,0"
        stroke-width="5"
        stroke="#000000"
        fill="none"
    ></path>
    <path
        d="m343,70c0,1 0.39417,4.01947 0,8c-0.50244,5.0742 -2.78394,16.11098 -8,26c-4.80331,9.10649 -8.83707,19.11604 -16,29c-5.8681,8.09724 -7.96854,13.41208 -10,17c-0.69678,1.23065 -2,2 -1,2c1,0 2.23462,-1.15224 3,-3c1.0824,-2.61313 3.31812,-4.59012 6,-7c5.80942,-5.22023 11.23273,-9.73325 17,-15c5.22144,-4.7683 10.97736,-10.09544 15,-11c4.97479,-1.11867 7,-2 10,-2c1,0 1,1 1,3c0,2 0,5 0,7c0,2 0.68927,4.08026 0,7c-1.54123,6.52875 -8,10 -12,14c-4,4 -10.07748,7.03891 -16,8c-6.24289,1.01308 -11.23401,3.49295 -16,6c-3.19098,1.67856 -5.58578,1.58578 -7,3c-0.70709,0.70711 -1,1 -1,3c0,1 0,3 0,6c0,4 -1.53073,8.30449 0,12c1.0824,2.61313 3,6 3,8c0,1 0,2 0,3c0,1 0,2 0,4c0,2 0.65482,5.17697 -1,10c-1.45139,4.23007 -3,9 -3,11c0,2 -0.70709,4.29289 0,5c0.70709,0.70711 5.12631,1.32375 12,0c5.28799,-1.01837 18.44205,-6.47672 30,-10c11.63684,-3.54733 22.81888,-7.23181 33,-15c10.81332,-8.25056 16.91034,-13.09831 19,-20c0.86935,-2.87128 0.4595,-7.0535 0,-9c-0.51373,-2.17625 -4.81146,-5.13464 -7,-8c-1.91949,-2.51308 -4,-5 -7,-7c-3,-2 -3.82376,-4.48625 -6,-5c-0.97324,-0.22975 -2,0 -3,0c-1,0 -2,0 -3,0c-1,0 -1.1731,0.85274 -2,2c-1.30746,1.814 -3,4 -3,9c0,2 -0.19385,9.03044 1,16c0.8609,5.02582 2.724,12.22273 6,16c4.63297,5.34187 8.19028,8.88152 10,12c1.12234,1.93399 1,3 1,4c0,1 0,4 0,6c0,3 0,10 0,13c0,7 0,16 0,29c0,7 0,10 0,17c0,4 -0.4588,5.69345 -1,7c-0.38269,0.92389 0,0 1,0l1,-1l1,-1"
        stroke-width="5"
        stroke="#000000"
        fill="none"
    ></path>
    <path
        d="m449,129c0,1 0,5 0,10c0,6 0,15 0,24c0,11 0,20 0,27c0,6 0,11 0,15c0,2 0,4 0,5c0,1 -1,1 -1,1c0,-1 -1.49829,-4.93796 -2,-11c-0.57736,-6.97615 -2,-16 -2,-27c0,-9 0,-18 0,-23c0,-3 -0.17557,-7.0979 1,-9c2.62866,-4.25325 4,-5 6,-7c2,-2 4,-3 7,-3c3,0 7,0 10,0c2,0 7.04132,-0.15277 11,1c3.03619,0.88414 4.37201,2.3851 8,5c1.14728,0.8269 2,2 2,3c0,2 0,3 0,4c0,2 0.4588,5.69345 1,7c0.76538,1.84776 1.83209,4.37875 6,6c6.78485,2.63921 11.69025,7.01297 20,9c8.80707,2.10596 16,3 25,3c9,0 16,0 22,0c4,0 6.58582,-1.41422 8,0c0.70709,0.70711 1,1 1,2c0,1 0,3 0,4c0,2 1.90778,4.49623 6,5c2.97754,0.36655 6.64752,1.97252 11,3c7.78601,1.83803 13.50659,-0.89528 21,-5c8.77039,-4.80421 12.14386,-11.90654 16,-18c3.1181,-4.92722 2.74567,-9.82132 0,-14c-4.42725,-6.73793 -11.58978,-12.44043 -18,-18c-7.55457,-6.55202 -14.92896,-14.92892 -22,-22c-7.07104,-7.07107 -16.30359,-12.37257 -23,-16c-6.34058,-3.43468 -9.30804,-5.90965 -13,-8c-3.58795,-2.03145 -6,-1 -10,-1c-2,0 -5.3045,-1.53073 -9,0c-3.91968,1.62359 -5.91876,5.34508 -8,10c-2.04083,4.56453 -5.97253,8.6475 -7,13c-0.68927,2.91975 0,5 0,9c0,2 -0.76538,4.15224 0,6c0.5412,1.30656 2.2594,2.99808 6,5c4.49567,2.40602 9.87854,1.49345 13,2c4.93542,0.80092 10,1 14,1c6,0 13,2 20,2c11,0 20,0 27,0c7,0 10,0 12,0c1,0 2.22974,-2.02675 2,-3c-0.51373,-2.17625 -2,-5 -6,-7c-2,-1 -5.25659,-0.41885 -10,-2c-4.74341,-1.58115 -5.64117,-5.55037 -10,-8c-4.69458,-2.63833 -8.96393,-5.08557 -16,-8c-4.97522,-2.06081 -6.87854,-3.49346 -10,-4c-0.98706,-0.16018 -0.61731,1.07612 -1,2c-1.0824,2.61313 -2,3 -2,4c0,1 0,2 0,3l0,1"
        stroke-width="5"
        stroke="#000000"
        fill="none"
    ></path>
</svg>
path {
    stroke-dasharray: 1000;
    stroke-dashoffset: 1000;
    animation: dash 5s linear infinite;
}

@keyframes dash {
    to {
        stroke-dashoffset: 0;
    }
}

image.png

解释: 首先使用stroke-dasharray属性设置一个尺寸足够大的虚线。由于stroke-dasharray属性先显示实色部分,再显示透明部分,因此,默认状态下,元素的描边就是实线效果。此时再设置stroke-dashoffset属性值,让虚线起始位置正好偏移实色部分的长度,这样描边显示的是透明部分,描边是不可见的。然后执行animation动画,让stroke-dashoffset属性值慢慢变成0,虚线的实色部分就会慢慢出现,于是一个描边动画效果就出现了

注意: 这种描边动画效果的实现不受SVG图形类型影响

<== 圆环进度条效果 ==>

举例:

circle {
    stroke-width: 50px;
    fill: none;
    stroke-dasharray: 1069px;
}

.circle-track {
    stroke: #f0f1f5;
}

.circle-bar {
    stroke-dashoffset: 1069px;
    stroke: url(#gradient);
}

.text {
    font-size: 50px;
}
<svg width="440" height="440" viewBox="0 0 440 440">
    <defs>
        <linearGradient x1="1" y1="0" x2="0" y2="0" id="gradient">
        <stop offset="0%" stop-color="#e52c5c"></stop>
        <stop offset="100%" stop-color="#ab5aea"></stop>
        </linearGradient>
    </defs>
    
    <circle cx="220" cy="220" r="170" class="circle-track"></circle>
    
    <circle
        cx="220"
        cy="220"
        r="170"
        transform="rotate(-90 220 220)"
        class="circle-bar"
    ></circle>
    
    <text
        class="text"
        x="50%"
        y="50%"
        dominant-baseline="middle"
        text-anchor="middle"
    >
        0%
    </text>
</svg>

<p>
    加载进度:
    <input type="range" id="range" min="0" max="100" value="0" />
</p>
var eleRange = document.querySelector("#range");
var eleBar = document.querySelector(".circle-bar");
var eleText = document.querySelector(".text");
eleRange.addEventListener("input", function () {
    var value = this.value;
    eleBar.style.strokeDashoffset = 1069 - (1069 * value) / 100 + "px";
    eleText.textContent = value + "%";
});

eleRange.addEventListener("change", function () {
    var value = this.value;
    eleBar.style.strokeDashoffset = 1069 - (1069 * value) / 100 + "px";
    eleText.textContent = value + "%";
});

image.png

解释: 设置两个SVG<circle>元素,下层的<circle>元素使用灰色描边,作为进度槽;上层的<circle>元素设置为虚线描边,同时使用渐变进行描边填充。然后通过改变stroke-dashoffset的属性值就可以让渐变描边一点一点地出现,于是一个彩色渐变圆环进度条效果就实现了

(4)CSS属性下的SVG标记

说明: SVG中的图形由三部分组成,分别是填充、描边和标记; 标记的作用是标记路径起止点和路径转折点,标记的图形可以是圆形、矩形、椭圆等常见的SVG图形。理论上,不使用标记元素也能对路径的起止点进行标记,额外绘制一个圆,与路径的起止点和转折点对齐即可,但是这样的成本比较高,尤其是当路径的数值发生变化的时候,标记元素的位置也会跟着一起变化。但是,如果用<marker>元素进行标记,只需要关心标记的形状是什么,标记图形会自动与路径的起止点或转折点对齐,并且标记图形是可以无限重复使用的

==> marker-start/end 起止标记 <==

说明: 无论是marker-start、marker-end还是marker-mid属性的使用,都需要在页面中提前设置<marker>标记元素,这个<marker>元素可以在一个单独的SVG中,也可以和需要使用标记效果的元素放在同一个SVG中

<svg width="0" height="0" style="position: absolute;">
    <defs>
        <!-- 定义原型标记 -->
        <marker id="markerCircle" markerWidth="8" markerHeight="8" refX="4" refY="4">
            <circle cx="4" cy="4" r="2.5">
        </marker>
        <!-- 定义三角形标记 -->
        <marker id="markerArrow" markerWidth="12" markerHeight="12" refX="2" refY="6" orient="auto">
            <path d="M2,3 L2,10 L8,6 L2,3">
        </marker>
    </defs>
</svg>

<p>
    My Love
    <!-- 画一条直线 -->
    <svg width="150" height="20" viewBox="0 0 150 20">
        <line x1="10" y1="10" x2="130" y2="10"></line>
    </svg>
    Your Heart
</p>
line {
    stroke: red;
    stroke-width: 2px;
    marker-start: url(#markerCircle);
    marker-end: url(#markerArrow);
}

image.png

==> marker-mid 转折点标记 <==

作用: 可以让元素在转折点位置显示标记

<svg width="0" height="0" style="position: absolute;">
    <defs>
        <marker id="markerCircle" markerWidth="8" markerHeight="8" refX="4" refY="4">
            <circle cx="4" cy="4" r="2.5" fill="#000">
        </marker>
        <marker id="markerArrow" markerWidth="12" markerHeight="12" refX="2" refY="6" orient="auto">
            <path d="M2,3 L2,10 L8,6 L2,3" fill="#000">
        </marker>
    </defs>
</svg>

<svg>
    <polyline points="20,100 50,60 80,80 110,20 140,60 170,40 200,90">
</svg>
polyline {
    fill: none;
    stroke: red;
    stroke-width: 2px;
    marker-mid: url(#markerCircle);
}

image.png

(5)其它常见的SVG CSS属性

==> paint-order 外描边效果 <==

作用: 可以用来设置是先绘制描边还是先绘制填充

说明: 在SVG中,同时设置描边和填充是很常见的,而SVG图形的描边和CSS中的-webkit-text-stroke描边是一样的,都是居中描边。居中描边就带来一个问题,如果描边再粗一点,说不定就看不见文字原本的颜色了,那就不是描边效果,而是加粗效果了,这并不符合预期,此时就需要paint-order来帮忙了

svg {
    background-color: deepskyblue;
    fill: crimson;
    stroke: white;
    stroke-width: 6px;
    font-size: 36px;
}

.paint-order {
    paint-order: stroke;
}
<svg>
    <text x="5" y="50">感谢</text>
    <text x="5" y="120" class="paint-order">感谢</text>
</svg>

image.png

解释: 因为填充是后执行的,所以文字的红色填充色覆盖了居中描边内侧的白色部分,视觉表现上就是外描边效果了

语法:

paint-order: normal;
paint-order: fill || stroke || markers;
  • normal: 是默认值,表示绘制顺序是fill、stroke、 markers,即先执行填充,再执行描边,最后执行标记

  • fill: 表示先执行填充

  • stroke: 表示先执行描边,再执行填充或者标记。之所以paint-order:stroke可以实现外描边效果,实际上是因为内侧的描边被填充覆盖了

  • markers: 表示先执行标记

==> vector-effect 描边不缩放 <==

特性: 设置了viewBox属性的SVG元素中的stroke描边默认会跟随SVG尺寸的变化而变化,这就是SVG的stroke描边的默认特性

.icon {
    width: 50px;
    height: 50px;
    fill: none;
    stroke-width: 2px;
    stroke: #2486ff;
    stroke-linecap: round;
}
<svg class="icon" viewBox="0 0 50 50">
    <circle cx="25" cy="25" r="20" />
    <path d="M25 15 L 25 35" />
    <path d="M15 25 L 35 25" />
</svg>

<svg class="icon" viewBox="0 0 50 50" style="width: 100px; height: 100px">
    <circle cx="25" cy="25" r="20" />
    <path d="M25 15 L 25 35" />
    <path d="M15 25 L 35 25" />
</svg>

image.png

说明: 有些时候,是希望图标无论尺寸多大,描边的大小都是设定的宽度值。这样,就算拉伸后的宽高比例与拉伸前不一致,图标表现也良好。此时,就可以使用vector-effect属性,使用的方法很简单,就是给对应的SVG设置vector-effect:non-scaling-stroke

circle, path { 
    vector-effect: non-scaling-stroke;
}

image.png

适用场景: vector-effect属性非常适合用在SVG尺寸自适应的场景中,例如一个波形SVG需要适应不同的页面容器,此时如果单纯地缩放SVG就会产生变形,使用vector-effect属性设置后就无惧尺寸变化了

==> text-anchor 文字水平居中 <==

说明: 主要用在SVG的<text>、<tspan>等元素上,用来设置元素设置的坐标值是作为文本元素的起点坐标、中心点坐标还是终点坐标。就行为表现而言,text-anchor有些类似CSS中的text-align属性,这里都是相对于水平x轴的值对齐的

语法:

text-anchor: start | middle | end

举例:

text { 
    text-anchor: middle; 
}
<svg> 
    <text x="50%" y="40%">
        感谢您对
        <tspan x="50%" y="60%">CSS<tspan>
        的支持
    </text> 
</svg>

image.png

==> dominant-baseline 文字垂直居中 <==

说明: dominant-baseline属性的作用是设置SVG中文本内容的对齐方式,它只能对<text>、<tspan>等元素生效

/* 常见的是baseline、middle和hanging这三个属性值 */
dominant-baseline: auto | baseline | text-bottom | alphabetic | ideographic | middle | central | mathematical | hanging | text-top;

image.png

==> alignment-baseline 和 dominant-baseline 的区别 <==

说明: 一般情况下这两个属性的区别不大,但是如果一段文本的字号有大有小的时候区别就出来了,dominant-baseline表示绝对主基线,会对文本整体进行垂直对齐设置;alignment-baseline是针对局部的文本进行垂直对齐设置

举例:

<h4 class="fill">alignment-baseline</h4>
<svg class="alignment-baseline">
    <text x="50%" y="50%">感谢xuexi<tspan>CSS<tspan></text>
</svg>

<h4 class="fill">dominant-baseline</h4>
<svg class="dominant-baseline">
    <text x="50%" y="50%">感谢xuexi<tspan>CSS<tspan></text>
</svg>
svg {
    border: 1px dotted;
}

text {
    font-size: 1.5rem;
    text-anchor: middle;
}

tspan {
    font-size: 2.25rem;
}

.dominant-baseline text {
    dominant-baseline: middle;
}

.alignment-baseline text {
    alignment-baseline: middle;
}

image.png