::marker 让文字序号更有意思
什么是 ::marker
CSS 伪元素 ::marker 是从 CSS Pseudo-Elements Level 3 开始新增,CSS Pseudo-Elements Level 4 中完善的一个比较新的伪元素,从 Chrome 86+ 开始得到浏览器的支持。
利用它,我们可以给元素添加一个伪元素,用于生成一个项目符号或者数字。 正常而言,我们有如下结构:
<ul>
<li>Contagious</li>
<li>Stages</li>
<li>Pages</li>
<li>Courageous</li>
<li>Shaymus</li>
<li>Faceless</li>
</ul>
默认不添加任何特殊的样式,它的样式大概是这样:
利用 ::marker 我们可以对序号前面的小圆点进行改造:
li {
padding-left: 12px;
cursor: pointer;
color: #ff6000;
}
li::marker {
content: '>';
}
就可以将小圆点改造成任意我们想要的:
::marker 伪元素的一些限制
首先,能够响应 ::marker 的元素只能是一个 list item譬如 ul 内部的 li,ol 内部的 li 都是 list item
当然,也不是说我们如果想在其他元素上使用就没有办法,除了 list item我们可以对任意设置了 display: list-item 的元素使用 ::marker 伪元素。
其次,对于伪元素内的样式,不是任何样式属性都能使用,目前我们只能使用这些:
- all font properties -- 所以字体属性相关
- color -- 颜色值
- the content property -- content 内容,类似于
::before伪元素 的 content,用于填充序号内容 - text-combine-upright (en-US), unicode-bidi and direction properties -- 文档书写方向相关
::marker 的一些应用探索
譬如我们经常见到标题前面的一些装饰:
或者,我们还可以使用 emoji 表情:
都非常适合使用 ::marker 来展示,注意用在非 list-item 元素上需要使用 display: list-item:
<h1>Lorem ipsum dolor sit amet</h1>
<h1>Lorem ipsum dolor sit amet</h1>
h1 {
display: list-item;
padding-left: 8px;
}
h1::marker {
content: '▍';
}
h1:nth-child(2)::marker {
content: '😅';
}
::marker 是可以动态变化的
有意思的是,::marker 还是可以动态变化的,利用这点,可以简单制作一些有意思的 hover 效果。
譬如这种,没被选中不开心,选中开心的效果:
li {
color: #000;
transition: .2s all;
}
li:hover {
color: #ff6000;
}
li::marker {
content: '😩';
}
li:hover::marker {
content: '😁';
}
搭配 counter 一起使用
可以观察到的是,::marker 伪元素与 ::before、::after 伪元素是非常类似的,它们都有一个 content 属性。
在 content 里,其实是可以作用一些简单的字符串加法操作的。利用这个,我们可以配合 CSS 计数器 counter-reset 和 counter-increment 实现给 ::marker 元素添加序号的操作。
假设我们有如下 HTML:
<h3>Lorem ipsum dolor sit amet.</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
<h3>Itaque sequi eaque earum laboriosam.</h3>
<p>Ratione culpa reprehenderit beatae quaerat voluptatibus, debitis iusto?</p>
<h3>Laudantium sapiente commodi quidem excepturi!</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
我们利用 ::marker 和 CSS 计数器 counter-increment 实现一个自动计数且 h3 前面带一个 emoji 表情的有序列表:
body {
counter-reset: h3;
}
h3 {
counter-increment: h3;
display: list-item;
}
h3::marker {
display: list-item;
content: "✔" counter(h3) " ";
color: lightsalmon;
font-weight: bold;
}
效果如下,实现了一个自动给 ::marker 元素添加序号的效果:
单行文本溢出省略
核心 CSS 语句
-
overflow: hidden;(文字长度超出限定宽度,则隐藏超出的内容)
-
white-space: nowrap;(设置文字在一行显示,不能换行)
-
text-overflow: ellipsis;(规定当文本溢出时,显示省略符号来代表被修剪的文本)
优点
-
无兼容问题
-
响应式截断
-
文本溢出范围才显示省略号,否则不显示省略号
-
省略号位置显示刚好
短板
- 只支持单行文本截断
适用场景
适用于单行文本溢出显示省略号的情况
Demo
<style>
.demo {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
<body>
<div class="demo">这是一段很长的文本</div>
</body>
示例图片
多行文本溢出省略(按行数)
○ 纯 CSS 实现方案
核心 CSS 语句
-
-webkit-line-clamp: 2;(用来限制在一个块元素显示的文本的行数,2 表示最多显示 2 行。为了实现该效果,它需要组合其他的 WebKit 属性)
-
display: -webkit-box;(和 1 结合使用,将对象作为弹性伸缩盒子模型显示 )
-
-webkit-box-orient: vertical;(和 1 结合使用 ,设置或检索伸缩盒对象的子元素的排列方式 )
-
overflow: hidden;(文本溢出限定的宽度就隐藏内容)
-
text-overflow: ellipsis;(多行文本的情况下,用省略号 “…” 隐藏溢出范围的文本)
优点
-
响应式截断
-
文本溢出范围才显示省略号,否则不显示省略号
-
省略号显示位置刚好
短板
- 兼容性一般:-webkit-line-clamp 属性只有 WebKit 内核的浏览器才支持
适用场景
- 多适用于移动端页面,因为移动设备浏览器更多是基于 WebKit 内核 Demo
<style>
.demo {
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>
<body>
<div class='demo'>这是一段很长的文本</div>
</body>
示例图片
○ 基于 JavaScript 的实现方案
优点
-
无兼容问题
-
响应式截断
-
文本溢出范围才显示省略号,否则不显示省略号
短板
-
需要 JS 实现,背离展示和行为相分离原则
-
文本为中英文混合时,省略号显示位置略有偏差
适用场景
- 适用于响应式截断,多行文本溢出省略的情况
Demo
当前仅适用于文本为中文,若文本中有英文,可自行修改
<script type="text/javascript">
const text = '这是一段很长的文本';
const totalTextLen = text.length;
const formatStr = () => {
const ele = document.getElementsByClassName('demo')[0];
const lineNum = 2;
const baseWidth = window.getComputedStyle(ele).width;
const baseFontSize = window.getComputedStyle(ele).fontSize;
const lineWidth = +baseWidth.slice(0, -2);
// 所计算的strNum为元素内部一行可容纳的字数(不区分中英文)
const strNum = Math.floor(lineWidth / +baseFontSize.slice(0, -2));
let content = '';
// 多行可容纳总字数
const totalStrNum = Math.floor(strNum * lineNum);
const lastIndex = totalStrNum - totalTextLen;
if (totalTextLen > totalStrNum) {
content = text.slice(0, lastIndex - 3).concat('...');
} else {
content = text;
}
ele.innerHTML = content;
}
formatStr();
window.onresize = () => {
formatStr();
};
</script>
<body>
<div class='demo'></div>
</body>
示例图片
多行文本溢出省略(按高度)
○ 多行文本溢出不显示省略号
核心 CSS 语句
-
overflow: hidden;(文本溢出限定的宽度就隐藏内容)
-
line-height: 20px;(结合元素高度,高度固定的情况下,设定行高, 控制显示行数)
-
max-height: 40px;(设定当前元素最大高度)
优点
-
无兼容问题
-
响应式截断
短板
- 单纯截断文字, 不展示省略号,观感上较为生硬
适用场景
- 适用于文本溢出不需要显示省略号的情况
Demo
<style>
.demo {
overflow: hidden;
max-height: 40px;
line-height: 20px;
}
</style>
<body>
<div class='demo'>这是一段很长的文本</div>
</body>
示例图片
○ 伪元素 + 定位实现多行省略
核心 CSS 语句
-
position: relative; (为伪元素绝对定位)
-
overflow: hidden; (文本溢出限定的宽度就隐藏内容)
-
position: absolute;(给省略号绝对定位)
-
line-height: 20px; (结合元素高度,高度固定的情况下,设定行高, 控制显示行数)
-
height: 40px; (设定当前元素高度)
-
::after {} (设置省略号样式)
优点
-
无兼容问题
-
响应式截断
短板
-
无法识别文字的长短,无论文本是否溢出范围, 一直显示省略号
-
省略号显示可能不会刚刚好,有时会遮住一半文字
适用场景
- 适用于对省略效果要求较低,文本一定会溢出元素的情况
Demo
<style>
.demo {
position: relative;
line-height: 20px;
height: 40px;
overflow: hidden;
}
.demo::after {
content: "...";
position: absolute;
bottom: 0;
right: 0;
padding: 0 20px 0 10px;
}
</style>
<body>
<div class='demo'>这是一段很长的文本</div>
</body>
示例图片
○ 利用 Float 特性,纯 CSS 实现多行省略
核心 CSS 语句
-
line-height: 20px;(结合元素高度,高度固定的情况下,设定行高, 控制显示行数)
-
overflow: hidden;(文本溢出限定的宽度就隐藏内容)
-
float: right/left;(利用元素浮动的特性实现)
-
position: relative;(根据自身位置移动省略号位置, 实现文本溢出显示省略号效果)
-
word-break: break-all;(使一个单词能够在换行时进行拆分)
优点
-
无兼容问题
-
响应式截断
-
文本溢出范围才显示省略号,否则不显示省略号
短板
- 省略号显示可能不会刚刚好,有时会遮住一半文字
适用场景
- 适用于对省略效果要求较低,多行文本响应式截断的情况
Demo
<style>
.demo {
background: #099;
max-height: 40px;
line-height: 20px;
overflow: hidden;
}
.demo::before{
float: left;
content:'';
width: 20px;
height: 40px;
}
.demo .text {
float: right;
width: 100%;
margin-left: -20px;
word-break: break-all;
}
.demo::after{
float:right;
content:'...';
width: 20px;
height: 20px;
position: relative;
left:100%;
transform: translate(-100%,-100%);
}
</style>
<body>
<div class='demo'>这是一段很长的文本</div>
</body>
示例图片
原理讲解
有 A、B、C 三个盒子,A 左浮动,B、C 右浮动。设置 A 盒子的高度与 B 盒子高度(或最大高度)要保持一致
-
当 B 盒子高度低于 A 盒子,C 盒子仍会处于 B 盒子右下方。
-
如果 B 盒子文本过多,高度超过了 A 盒子,则 C 盒子不会停留在右下方,而是掉到了 A 盒子下。
-
接下来对 C 盒子进行相对定位,将 C 盒子位置向右侧移动 100%,并向左上方向拉回一个 C 盒子的宽高(不然会看不到哟)。这样在文本未溢出时不会看到 C 盒子,在文本溢出时,显示 C 盒子。
纯css实现:文字被颜色逐渐填满的特效
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Document</title>
<style>
.box {
width: 888px;
height: 300px;
margin: 200px auto;
position: relative;
}
p {
position: absolute;
top: 0;
left: 0;
font-size: 36px;
font-weight: 600;
}
#text {
color: #666;
}
#copyText {
color: rgb(253, 145, 145);
}
#inner {
color: transparent;
background: linear-gradient(to right, #abdcff, #0396ff);
-webkit-background-clip: text;
background-repeat: no-repeat;
animation: landIn 10s linear;
}
@keyframes landIn {
0% {
background-size: 0 100%;
}
100% {
background-size: 79em 100%;
}
}
</style>
</head>
<body>
<div class="box">
<p id="text">
世界上只有一种真正的英雄主义,就是认清了生活的真相后还依然热爱它!
</p>
<p id="copyText">
<span id="inner"
>世界上只有一种真正的英雄主义,就是认清了生活的真相后还依然热爱它!</span
>
</p>
</div>
</body>
</html>
打字效果
<!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>
.wrapper {
height: 100vh;
/*This part is important for centering*/
display: flex;
align-items: center;
justify-content: center;
}
.typing-demo {
width: 22ch;
animation: typing 2s steps(22), blink 0.5s step-end infinite alternate;
white-space: nowrap;
overflow: hidden;
border-right: 3px solid;
font-family: monospace;
font-size: 2em;
}
@keyframes typing {
from {
width: 0;
}
}
@keyframes blink {
50% {
border-color: transparent;
}
}
</style>
</head>
<body>
<div class="wrapper">
<div class="typing-demo">这是一个打字演示。</div>
</div>
</body>
</html>
图片非透明区域添加投影
当您使用透明图像时,您可以使用 drop-shadow() 过滤器函数在图像内容上创建阴影,而不是使用 box-shadow 属性在元素的整个框后面创建矩形阴影:filter: drop-shadow(2px 4px 8px #585858);
<!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>
.wrapper {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.mr-2 {
margin-right: 2em;
}
.mb-1 {
margin-bottom: 1em;
}
.text-center {
text-align: center;
}
.box-shadow {
box-shadow: 2px 4px 8px #585858;
}
.drop-shadow {
filter: drop-shadow(2px 4px 8px #585858);
}
</style>
</head>
<body>
<div class="wrapper">
<div class="mr-2">
<div class="mb-1 text-center">box-shadow</div>
<img
class="box-shadow"
src="https://markodenic.com/man_working.png"
alt="Image with box-shadow"
/>
</div>
<div>
<div class="mb-1 text-center">drop-shadow</div>
<img
class="drop-shadow"
src="https://markodenic.com/man_working.png"
alt="Image with drop-shadow"
/>
</div>
</div>
</body>
</html>
平滑滚动
不需要 JavaScript 就可以实现平滑滚动,只需一行 CSS。
<!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>
html {
scroll-behavior: smooth;
}
nav {
position: fixed;
left: calc(50vw - 115px);
top: 0;
width: 200px;
text-align: center;
padding: 15px;
background: #fff;
box-shadow: 0 2px 5px 1px rgba(0, 0, 0, 0.2);
}
nav .link {
padding: 5px;
color: white;
}
.section {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 5em;
text-shadow: 0px 2px 0px #b2a98f, 0px 4px 3px rgba(0, 0, 0, 0.15),
0px 8px 1px rgba(0, 0, 0, 0.1);
}
.bg-red {
background: #de5448;
}
.bg-blue {
background: #4267b2;
}
.bg-green {
background: #4caf50;
}
</style>
</head>
<body>
<nav>
Scroll to:
<a href="#sectionA" class="link bg-red">A</a>
<a href="#sectionB" class="link bg-blue">B</a>
<a href="#sectionC" class="link bg-green">C</a>
</nav>
<div class="wrapper">
<div id="sectionA" class="section bg-red">A</div>
<div id="sectionB" class="section bg-blue">B</div>
<div id="sectionC" class="section bg-green">C</div>
</div>
</body>
</html>
光标
您知道如何使用自己的图像,甚至是表情符号作为光标吗?
<!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>
.wrapper {
display: flex;
height: 100vh;
align-items: center;
justify-content: center;
background: #4776e6;
background: -webkit-linear-gradient(to right, #4776e6, #8e54e9);
background: linear-gradient(to right, #4776e6, #8e54e9);
padding: 0 10px;
}
.tile {
width: 200px;
height: 200px;
display: flex;
align-items: center;
justify-content: center;
background-color: #de5448;
margin-right: 10px;
color: #fff;
font-size: 1.4em;
text-align: center;
}
.tile--image-cursor {
background-color: #1da1f2;
cursor: url(https://picsum.photos/20/20), auto;
}
.tile--emoji-cursor {
background-color: #4267b2;
cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='48' viewport='0 0 100 100' style='fill:black;font-size:24px;'><text y='50%'>🚀</text></svg>"),
auto;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="tile">Default</div>
<div class="tile tile--image-cursor">Image Cursor</div>
<div class="tile tile--emoji-cursor">Emoji Cursor</div>
</div>
</body>
</html>
::selection CSS 伪元素
::selection CSS 伪元素可以自定义控制鼠标选中部分内容的样式。
<!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>
.wrapper {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
p {
font-size: 2rem;
font-family: sans-serif;
}
.custom-highlighting::selection {
background-color: #8e44ad;
color: #fff;
}
</style>
</head>
<body>
<div class="wrapper">
<div>
<p>这是默认高亮显示。鼠标选中试试看。</p>
<p class="custom-highlighting">这是自定义高亮显示。鼠标选中试试看。</p>
</div>
</div>
</body>
</html>
万物皆可伸缩
你知道任何元素调整大小,都可以像 <textarea> 一样吗?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Document</title>
<style>
div {
border: 2px solid;
padding: 10px 40px;
width: 300px;
/* 核心代码 */
resize: both;
overflow: auto;
}
</style>
</head>
<body>
<p><b>注意:</b> Firefox, Safari,和 Chrome 兼容 resize 属性.</p>
<div>调整属性指定一个元素是否由用户可调整大小的。</div>
</body>
</html>
CSS 模态框
你可以使用 :target 伪类来创建零 JavaScript 的模态。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Document</title>
<style>
.wrapper {
height: 100vh;
/* This part is important for centering the content */
display: flex;
align-items: center;
justify-content: center;
/* End center */
background: -webkit-linear-gradient(to right, #834d9b, #d04ed6);
background: linear-gradient(to right, #834d9b, #d04ed6);
}
.wrapper a {
display: inline-block;
text-decoration: none;
padding: 15px;
background-color: #fff;
border-radius: 3px;
text-transform: uppercase;
color: #585858;
font-family: "Roboto", sans-serif;
}
.modal {
visibility: hidden;
opacity: 0;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(77, 77, 77, 0.7);
transition: all 0.4s;
}
.modal:target {
visibility: visible;
opacity: 1;
}
.modal__content {
border-radius: 4px;
position: relative;
width: 500px;
max-width: 90%;
background: #fff;
padding: 1em 2em;
}
.modal__footer {
text-align: right;
}
.modal__close {
position: absolute;
top: 10px;
right: 10px;
color: #585858;
text-decoration: none;
}
</style>
</head>
<body>
<div class="wrapper">
<a href="#demo-modal">打开模态框</a>
</div>
<div id="demo-modal" class="modal">
<div class="modal__content">
<h1>CSS 实现模态框</h1>
<p>
您可以使用 :target 伪类创建零 JavaScript 的模态框。赶紧一起玩一玩啊!
</p>
<div class="modal__footer">
Made with <i class="fa fa-heart"></i>, by
<a href="https://juejin.cn/user/958429872534056/posts" target="_blank"
>@gyx_这个杀手不太冷静</a
>
</div>
<a href="#" class="modal__close">×</a>
</div>
</div>
</body>
</html>
CSS 滚动捕捉优化滚动体验
您可以控制 scroll-snap-type 值来获取良好的滚动体验:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Document</title>
<style>
body {
margin: 0;
padding: 0;
}
.wrapper {
height: 100vh;
overflow: auto;
scroll-snap-type: y mandatory;
}
.section {
scroll-snap-align: center;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #de5448;
color: #fff;
font-size: 3em;
}
.bg-blue {
background: #4267b2;
}
.bg-green {
background: #4caf50;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="section">Content 1</div>
<div class="section bg-blue">Content 2</div>
<div class="section bg-green">Content 3</div>
<div class="section">Content 4</div>
<div class="section bg-blue">Content 5</div>
</div>
</body>
</html>
CSS 动态文字提示
使用 attr() CSS 函数创建动态的仅用 CSS 实现文字提示。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Document</title>
<style>
body {
padding: 20px;
}
.tooltip {
position: relative;
border-bottom: 1px dotted black;
}
/* Tooltip box */
.tooltip:before {
content: attr(data-tooltip);
position: absolute;
width: 100px;
background-color: #062b45;
color: #fff;
text-align: center;
padding: 10px;
line-height: 1.2;
border-radius: 6px;
z-index: 1;
opacity: 0;
transition: opacity 0.6s;
bottom: 125%;
left: 50%;
margin-left: -60px;
font-size: 0.75em;
visibility: hidden;
}
/* Tooltip arrow */
.tooltip:after {
content: "";
position: absolute;
bottom: 75%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
opacity: 0;
transition: opacity 0.6s;
border-color: #062b45 transparent transparent transparent;
visibility: hidden;
}
.tooltip:hover:before,
.tooltip:hover:after {
opacity: 1;
visibility: visible;
}
</style>
</head>
<body>
<h1>HTML/CSS 文字提示</h1>
<p>
鼠标移入<span class="tooltip" data-tooltip="这是一个文字提示">这里</span
>显示文字提示。
</p>
<p>
你也可以移入<span class="tooltip" data-tooltip="这是另一个文字提示"
>这里</span
>显示另一个文字提示。
</p>
</body>
</html>
输入框光标颜色
您可以更改文本输入框光标的颜色。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Document</title>
<style>
input {
caret-color: red;
}
</style>
</head>
<body>
<input type="text" />
</body>
</html>
::in-range 和 ::out-of-range 伪类
使用 ::in-range 和 ::out-of-range 伪类来设置当前值超出 min 和 max 属性指定的范围限制的输入的样式。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Document</title>
<style>
input:in-range {
background-color: rgba(0, 255, 0, 0.25);
border: 1px solid green;
}
input:out-of-range {
background-color: rgba(255, 0, 0, 0.25);
border: 1px solid red;
}
</style>
</head>
<body>
<form>
<label for="one">输入 1 - 10 之间的一个数值</label>
<input type="number" id="one" name="one" min="1" max="10" />
<br />
<label for="two">输入 1 - 10 之间的一个数值</label>
<input type="number" id="two" name="two" min="1" max="10" />
</form>
</body>
</html>
花里胡哨的文字
使用 background-clip 属性创建漂亮的标题。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Document</title>
<style>
h1 {
background: blue url("https://picsum.photos/id/1015/200/300");
background-clip: text;
-webkit-background-clip: text;
color: transparent;
margin-top: 20px;
font-size: 120px;
}
@media (max-width: 600px) {
h1 {
font-size: 45px;
}
}
</style>
</head>
<body>
<h1>揭秘 CSS</h1>
</body>
</html>