文字超出显示省略号

正常的文字显示如下:

normal

当文字超出时,显示如下:

ellipsis

.span-text {
  display: inline-block;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 150px;
/ / 正常文字的宽度, 超出后显示省略号 white-space: nowrap;
/ / 不换行

}
<span class="span-text">567890owaijdhwabndjh4364356765432456db</span>

CSS动画--animation

1. 通过@keyframes定义动画

@keyframes animationName {
  from {
    properties: value;
  }
  percentage {
    properties: value;
  }
  to {
    properties: value;
  }
}

关键帧的语法:

描述
animationName规定需要绑定到选择器的 keyframe 名称
from动画的开始状态。在动画开始之前,动画属性的值将匹配 from 关键帧中的值
to动画的结束状态(等同于 100%)。在动画完成之后,动画属性的值将匹配 to 关键帧中的值
percentage0% 到 100% 之间的值。允许使用小数值
properties不同的样式属性名称,例如 color、left、width 等等

一个简单的例子:

@keyframes ball {
  0% {
    top: 0;
    left: 0;
  }
  25% {
    top: 0;
    left: calc(100% - 100px);
  }
  50% {
    top: 200px;
    left: calc(100% - 100px);
  }
  75% {
    top: 200px;
    left: 0;
  }
  100% {
    top: 0;
    left: 0;
  }
}

2. 通过animation绑定动画

animation: name duration timing-function delay iteration-count direction fill-mode play-state;

动画创建好后,还需要将动画应用到指定的 HTML 元素。要将动画应用到指定的 HTML 元素需要借助 CSS 属性,CSS 中提供了如下所示的动画属性:

属性名描述
animation所有动画属性的简写属性, 请注意,animation 属性必须设置动画名称和动画持续时间。
animation-name规定需要绑定到选择器的 keyframe 名称
animation-duration规定完成动画所花费的时间,以秒或毫秒计
animation-timing-function规定动画的速度曲线
animation-delay规定在动画开始之前的延迟
animation-iteration-count规定动画应该播放的次数
animation-direction规定是否应该轮流反向播放动画
animation-fill-mode规定对象动画时间之外的状态
animation-play-state设置动画是正在运行还是暂停,默认是 running

其中一些属性是可选的,但是 animation-name 和 animation-duration 属性是必须的。

一下是一些属性可选的值:

属性名描述
animation-timing-functionlinear, ease, ease-in, ease-out, ease-in-out, cubic-bezier(n,n,n,n)
animation-iteration-countinfinite, number
animation-directionnormal, reverse, alternate, alternate-reverse
animation-fill-modenone, forwards, backwards, both
animation-play-statepaused, running

animation-name

animation-name 属性规定需要绑定到选择器的 keyframe 名称。

属性名描述
none默认值。没有动画效果
name规定 @keyframes 动画的名称, 可以同时绑定多个动画,动画名称之间使用逗号进行分隔

animation-duration

animation-duration 属性规定完成动画所花费的时间,以秒或毫秒计。

animation-timing-function

animation-timing-function 属性规定动画的速度曲线。

属性名描述
linear动画从头到尾的速度是相同的。
ease默认。动画以低速开始,然后加快,在结束前变慢。
ease-in动画以低速开始。
ease-out动画以低速结束。
ease-in-out动画以低速开始和结束。
cubic-bezier(n,n,n,n)在 cubic-bezier 函数中自己的值。可能的值是从 0 到 1 的数值。

如下示例所示

最后一个为cubic-bezier(0, 0.1, 0.3, 0.8)的效果

ease
ease-in
ease-out
ease-in-out
cubic-bezier

animation-fill-mode

animation-fill-mode 属性规定对象动画时间之外的状态。

属性名描述
none默认值。动画不会将任何样式应用于动画结束时的元素。它会在动画开始之前应用样式,然后在动画完成后删除样式。
forwards动画将应用于动画结束时的样式。这意味着动画完成后,元素将保留动画的最后一个属性值。
backwards在 animation-delay 所指定的时间段内,应用动画第一个关键帧中的样式
both动画将遵循 forwards 和 backwards 的规则,从而在两个方向上扩展动画属性。

css关键帧如下:

恭喜你中大奖了, 继续往下面学习吧 !
@keyframes loto {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(calc(360deg * var(--random-rotation)));
  }
}

...
// 应用动画
animation: loto

3
s forwards

;

--random-rotation是一个自定义属性,它的值是一个随机数,这个随机数是通过js生成的

const randomRotation = Math.random() * 30
const container = document.querySelector(".big-background")
container.style.setProperty("--random-rotation", randomRotation)

animation-iteration-count

animation-iteration-count 属性规定动画应该播放的次数。

属性名描述
number定义动画播放次数。默认是 1
infinite动画应该无限次播放。

animation-direction

animation-direction 属性规定是否应该轮流反向播放动画。

属性名描述
normal默认值。动画应该正常播放。
reverse动画应该反向播放。
alternate动画应该轮流反向播放。
播放动画时,奇数次(1、3、5 等)正常播放,偶数次(2、4、6 等)反向播放
alternate-reverse动画应该轮流反向播放,并且每次迭代都以相反的方向开始。
播放动画时,奇数次(1、3、5 等)反向播放,偶数次(2、4、6 等)正常播放

animation-play-state

animation-play-state 属性设置动画是正在运行还是暂停。

属性名描述
paused指定动画已暂停。
running指定动画正在运行。

以下是综合案例:

动画的时间线--animation-timeline

当我们的动画效果需要跟滚动条配合时,我们可以使用animation-timeline来实现( 有兼容性问题 )

监听垂直滚动条时: animation-timeline: scroll(y);

监听水平滚动条时: animation-timeline: scroll(x);

在下面的预览中可以发现, 即时当滚动条滚动到最底部时, 顶部的进度条似乎没有到达最右边

其实最右边的区域是滚动条的宽度

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99

结构如下:


<template>
  <div class="container">
    <div class="main">
      <div class="top-line"></div>
      <ul>
        <li v-for="item in 99" :key="item">{{ item }}</li>
      </ul>
    </div>
  </div>
</template>
@keyframes line {
  from {
    width: 0;
  }
  to {
    width: 100%;
  }
}

.container {
  width: 100%;
  height: 300px;
  border: 1px solid rebeccapurple;
}

.main {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: auto;
}

.top-line {
  position: sticky;
  top: 0;
  height: 2px;
  background-color: #e1732e;
  z-index: 999;
  animation: line 5s linear;
  animation-timeline: scroll(y);
}

由HTML的结构可知, <div class="top-line"></div>就是顶部的进度条, 放在main容器中,因此监听的滚动事件是main容器的滚动事件

当需要监听整个页面的滚动事件时, 可以将<div class="top-line"></div>放在<body></body>

Svg实现描边动画

通过这个示例, 可以实现其他svg的描边动画

注意, 我们应该给SVG的路径元素添加一个类名,以便我们可以选择这些元素并为它们设置描边动画<path class="svg", <line class="svg"


<template>
  <div>
    <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="none"
        stroke-linecap="round"
        stroke-linejoin="round"
        class="feather feather-arrow-right"
    >
      <line class="svg" x1="5" y1="12" x2="19" y2="12"></line>
      <polyline class="svg" points="12 5 19 12 12 19"></polyline>
    </svg>
    <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 1024 1024"
        version="1.1"
        width="200"
        height="200"
    >
      <path class="svg"
          d="M598.42265 1024c-14.175779 0-28.351557-5.439915-39.07139-16.287746L16.287746 464.64874A55.67913 55.67913 0 0 1 0 425.417353c0-14.71977 5.919908-28.767551 16.287746-39.231387l69.75891-69.566913A154.557585 154.557585 0 0 1 196.092936 271.051765c41.567351 0 80.63874 16.159748 110.11028 45.663286l2.367963 2.335964 237.116295-237.212294c109.374291-109.118295 287.195513-109.118295 396.217809 0A278.139654 278.139654 0 0 1 1023.984 280.107623c0 74.87883-29.215544 145.181732-82.110717 198.204903l-237.020296 237.084296 2.335963 2.335963a155.101577 155.101577 0 0 1 45.631287 110.270277 154.781582 154.781582 0 0 1-45.631287 110.270277l-69.534913 69.566913A55.67913 55.67913 0 0 1 598.39065 1024zM133.78991 425.513351l464.63274 464.792738 30.463524-30.463524c8.511867-8.511867 13.215794-19.87169 13.215793-31.967501s-4.703927-23.423634-13.215793-31.935501l-41.439353-41.439352a55.487133 55.487133 0 0 1 0-78.334776l276.219684-276.283683a168.445368 168.445368 0 0 0 49.695224-119.902127c0-45.279293-17.599725-87.67863-49.695224-119.774128-65.95097-65.982969-173.501289-65.982969-239.708254 0.127998l-276.219684 276.283683a55.423134 55.423134 0 0 1-78.302777 0L227.996438 395.209825c-17.023734-17.023734-46.591272-17.023734-63.615006 0l-30.591522 30.335526z m134.3979 596.150685A55.487133 55.487133 0 0 1 229.11642 927.041515l56.511117-56.511117a55.423134 55.423134 0 0 1 78.302777 0c21.567663 21.567663 21.567663 56.639115 0 78.334776l-56.479118 56.607115a55.67913 55.67913 0 0 1-39.199387 16.159748z"
          fill="#409EFF"></path>
      <path class="svg"
          d="M608.66249 386.665958c-14.175779 0-28.351557-5.439915-39.07139-16.159747a55.487133 55.487133 0 0 1 0-78.302777l56.479118-56.511117a55.423134 55.423134 0 0 1 78.302776 0c21.567663 21.599663 21.567663 56.639115 0 78.334776l-56.479117 56.479118a55.67913 55.67913 0 0 1-39.231387 16.159747zM60.287058 813.699286a55.487133 55.487133 0 0 1-39.103389-94.590522l56.511117-56.511117a55.423134 55.423134 0 0 1 78.302777 0c21.567663 21.599663 21.567663 56.639115 0 78.334776L99.518445 797.41154c-10.87983 10.87983-25.023609 16.287746-39.231387 16.287746z"
          fill="#409EFF"></path>
    </svg>
  </div>
</template>
.svg {
  stroke-width: 2;
  stroke: black;
  fill: gold;
  animation: draw 4s linear infinite, fill 4s forwards;
}

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

@keyframes fill {
  to {
    fill: #409EFF;
  }
}
// 获取所有带有.svg类的SVG路径元素
const paths = document.querySelectorAll('.svg')
// 遍历所有带有.svg类的路径元素
paths.forEach((path) => {
  // 获取路径的长度
  const length = path.getTotalLength()
  // 设置stroke-dasharray和stroke-dashoffset属性以应用描边动画
  path.style.strokeDasharray = length
  path.style.strokeDashoffset = length
})

蜂巢布局

先看效果😂:

全部代码

CSS裁剪六边形, 通过网站获取:

CSS Clip-path 网站1open in new window

CSS Clip-path 网站2open in new window

<template>
  <div class="honeycomb">
    <div v-for="(line, index) in lines" class="line" :key="index">
      <div
          v-for="(item, idx) in items"
          class="item"
          :data-even="(index + 1) % 2 === 0"
          :id="index * items + idx"
          :key="idx"
          @mouseenter="hoverItem"
          @mouseleave="leaveItem"
      />
    </div>
  </div>
</template>

<script>
export default {
  name: 'Honeycomb',
  data: () => {
    return {
      lines: 6,
      items: 10,
    }
  },
  methods: {
    // 鼠标移入item时, 放大该item, 周围的item缩小
    hoverItem(e) {
      const target = e.target
      target.style.transform = 'scale(1.2)'
      // 过渡动画
      target.style.transition = 'transform 0.5s'

      // 获取周围的item的id
      const around = this.getAroundItems(target)
      // 周围的item缩小
      around.forEach(id => {
        const item = document.getElementById(id)
        if (item) {
          item.style.transform = 'scale(0.8)'
          item.style.transition = 'transform 0.5s'
        }
      })
    },
    // 鼠标移出item时, 恢复原始大小
    leaveItem(e) {
      const target = e.target
      target.style.transform = 'scale(1)'
      const around = this.getAroundItems(target)
      around.forEach(id => {
        const item = document.getElementById(id)
        if (item) {
          item.style.transform = 'scale(1)'
          item.style.transition = 'transform 0.5s'
        }
      })

    },
    // 获取目标item的周围item
    getAroundItems(target) {
      const id = Number(target.id)
      // 由于偶数行偏移, 需要特殊处理, 当当前target在偶数行时, 上面一行需要减一而下面的需要加一
      let offset = 1
      // 当前在偶数行 通过data-even属性判断
      if (target.dataset.even === 'true') {
        offset = -1
      }
      // 获取上面两个相邻的id 当前id减去items的数量
      const top = [id - this.items, id - this.items + offset]
      // 获取本行两个相邻的id
      const middle = [id - 1, id + 1]
      // 获取下面两个相邻的id 当前id加上items的数量
      const bottom = [id + this.items + offset, id + this.items]

      return [...top, ...middle, ...bottom]
    },
  },
}
</script>

<style lang="less" scoped>
@line: 6;
@item: 10;
@itemWidth: calc(100% / @item);
@lineHeight: calc(100% / @line);

.honeycomb {
  display: flex;
  flex-wrap: wrap;
  overflow: hidden;

  .line {
    width: 100%;
    display: flex;
    gap: 10px;
    justify-content: space-between;
    // 偶数行偏移
    &:nth-child(even) {
      transform: translateX(-38px);
    }

    &:nth-child(n+2) {
      margin-top: -10px;
    }

    .item {
      width: @itemWidth;
      height: 65px;
      // 保持正六边形 空间不够不压缩
      flex-shrink: 0;
      background-color: #21dede;
      clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
    }
  }
}
</style>

保持元素宽高比

使用新的CSS属性aspect-ratio

先看效果

拖动窗口可以发现, 宽高比保持不变

aspect-ratio: 4 / 3; 表示宽高比为4:3

但是这个属性只有谷歌浏览器2021年以后的才支持, ie全部不支持

<template>
<div class="item"></div>
</template>

<script>
export default {
  name: 'Proportion',
}
</script>

<style scoped>
.item {
  background-color: #3eaf7c;
  width: 50%;
  margin: 0 auto;
  /** 保持宽高比为4:3 */
  aspect-ratio: 4 / 3;
}
</style>

使用padding

先看效果

这样就可以实现一个宽高比为 4:3 的容器了。

由于padding是基于父元素的宽度, 因此可以通过设置padding-top来实现宽高比

但是这个inner是没有高度的, 无法在里面写内容, 我们需要再套一层

<template>
  <div class="item">
    <div class="inner">
      <div class="container">
        这样就可以实现一个宽高比为 4:3 的容器了。
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Proportion',
}
</script>

<style scoped lang="less">
.item {
  background-color: #3eaf7c;
  width: 50%;
  margin: 0 auto;

  .inner {
    width: 100%;
    padding-top: 75%;
    background-color: #2c2e40;
    position: relative;
  }

  .container {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: #f00;
  }
}
</style>

可以做成一个组件, 实现宽高比的自定义, 以及内容的自定义

文字下划线动画

先看示例后看代码:

CSS 下划线动画主要是通过背景的渐变色来实现的, 通过调整背景的渐变色的位置和颜色以及其宽度来实现下划线动画效果。 当鼠标移动到文本上时, 下划线会从左到右的移动, 当鼠标移出文本时, 下划线会从右到左的移动。

background属性

background的可取值如下

描述
background-color规定背景颜色。默认值是 "transparent"。
background-image规定一个或多个背景图像。默认值是 "none"。
background-repeat规定如何重复背景图像。默认值是 "repeat"。
background-attachment规定背景图像是否固定或者随着页面的其余部分滚动。默认值是 "scroll"。
background-position规定背景图像的位置。默认值是 "0% 0%"。
background-clip规定背景的绘制区域。默认值是 "border-box"。
background-origin规定背景图片的定位区域。默认值是 "padding-box"。
background-size规定背景图片的尺寸。默认值是 "auto"。

background-position的值可以是关键字, 百分比, 长度值, 两个关键字组合

描述
top图像的顶部与容器的顶部对齐。
bottom图像的底部与容器的底部对齐。
left图像的左侧与容器的左侧对齐。
right图像的右侧与容器的右侧对齐。
center图像的中心与容器的中心对齐。
x% y%图像的左上角与容器的左上角对齐。第一个值是水平位置,第二个值是垂直位置。两个值都是百分比。
x-pos y-pos第一个值是水平位置,第二个值是垂直位置。可能的值是 top, center, bottom, left, right。

transition属性

transition属性是一个简写属性, 用于设置四个过渡属性的速记属性

属性名描述
transition-property规定应用过渡的 CSS 属性的名称。默认是所有属性。
transition-duration规定完成过渡效果需要多少秒或毫秒。默认是 0。
transition-timing-function规定速度效果的速度曲线。默认是 "ease"。
transition-delay定义过渡效果何时开始。默认是 0。

transition-property常见的值有:

描述
all默认值。所有属性都将获得过渡效果。
none没有属性会获得过渡效果。
property定义应用过渡效果的 CSS 属性的名称。
multiple定义应用过渡效果的多个 CSS 属性的名称。

transition-timing-function的值可以是以下之一:

描述
linear规定以相同速度开始至结束的过渡效果。
ease规定慢速开始,然后变快,然后慢速结束的过渡效果。
ease-in规定以慢速开始的过渡效果。
ease-out规定以慢速结束的过渡效果。
ease-in-out规定以慢速开始和结束的过渡效果。
cubic-bezier(n,n,n,n)在 cubic-bezier 函数中自己的值。可能的值是从 0 到 1 的数值。

代码

<template>
  <div class="container">
    <span class="text">
      CSS 下划线动画主要是通过背景的渐变色来实现的, 通过调整背景的渐变色的位置和颜色以及其宽度来实现下划线动画效果。
      当鼠标移动到文本上时, 下划线会从左到右的移动, 当鼠标移出文本时, 下划线会从右到左的移动。
    </span>
  </div>
</template>
<script>
export default {
  name: 'TextLine',
}
</script>
<style lang="less" scoped>
.container {
  line-height: 2;

  .text {
    background: linear-gradient(to right, #ff4e50, #f9d423) no-repeat right bottom;
    /* 一开始宽度为0 */
    background-size: 0 2px;
    /* 背景尺寸的动画 2s 匀速 */
    transition: background-size 2s linear;

    &:hover {
      /* 鼠标移动到文本上时, 下划线会从左到右的移动 */
      background-position: left bottom;
      background-size: 100% 2px;
    }
  }
}
</style>
Last Updated:
Contributors: huangdingxin