CSS 技巧

评判一个网页的美观程度,首要的当然是看它的 CSS 样式写的如何。

日本某宅写了一个非常厨二的页面——臆病な魔女,可以说是把 CSS 动画玩得非常 6 了,看得笔者顿时燃起了学好 CSS 的欲望。

如果想 CSS 玩的溜,除了熟悉基本的知识以外,掌握大量技巧也是必不可少的。

形状

扩张式矩形

目的:创建一个矩形,鼠标悬浮时扩张一定的大小

预览

<div class="expanding-box"></div>
body {
  display: flex;
  height: 100vh;
  justify-content: center;
  align-items: center;
}

.expanding-box {
  position: relative;
  width: 15em;
  height: 10em;

  &::after {
    position: absolute;
    content: "";
    top: -1em;
    right: -1em;
    bottom: -3em;
    left: -1em;
    background: black;
    --path: inset(2rem 0 2rem 2rem round 10px);
    clip-path: var(--path);
    transition: clip-path 0.3s;
  }

  &:hover::after {
    --path: inset(0 round 10px);
  }
}

首先利用伪元素::after生成一个矩形

利用clip-pathinset来裁切矩形(顺序是上右下左圆角)

鼠标悬浮时去除裁切效果即可

字体排印

分割符

目的:实现分隔符效果

预览

<ul>
  <li><a href="#">Home</a></li>
  <li><a href="#">Archive</a></li>
  <li><a href="#">About</a></li>
</ul>
ul {
  display: flex;
  font-weight: bold;
  list-style-type: none;

  li {
    &:not(:last-child) {
      margin-right: 5px;

      &::after {
        content: "|";
        margin-left: 5px;
      }
    }
  }
}

添加伪元素::after,内容content: "|",设置间距

再用:not(:last-child)去除伪元素的最后一个子元素即可

用户体验

提示用角标

目的:在按钮右上角创建一个提示用的角标

预览

<button class="badge" count="7">消息</button>
body {
  display: flex;
  justify-content: center;
}

button {
  position: relative;
  padding: 20px;
  border-radius: 20px;
  font-size: 24px;
}

.badge::before {
  content: attr(count);
  position: absolute;
  right: 10px;
  top: -8px;
  background: tan;
  padding: 0 8px;
  border-radius: 12px;
  transform: translate(50%, 0);
}

伪元素的content可通过attr()来获取标签的某一属性值

类似的提示框也可以配合过渡动画来实现:预览

伸缩式按钮

目的:实现伸缩式按钮(鼠标悬浮按钮则展开,移开按钮则收缩)

预览

<a href="#" class="sliding-button">
  <span>下载</span>
  <span>720p</span>
</a>
<a href="#" class="sliding-button">
  <span>下载</span>
  <span>1080p</span>
</a>
$tianyi-blue: #66ccff;

body {
  display: flex;
  height: 100vh;
  align-items: center;
  justify-content: center;
}

.sliding-button {
  background: $tianyi-blue url(https://i.loli.net/2019/09/04/JULm1Agr5Gzy7iK.png)
    no-repeat -30px center;
  overflow: hidden;
  transition: padding 0.2s ease, background-position 0.2s ease,
    transform 0.5s ease;

  border: 1px solid $tianyi-blue;
  border-radius: 4px;
  color: #fff;
  text-decoration: none;
  text-transform: uppercase;
  padding: 6px 16px 6px 16px;
  font-size: 18px;
  font-weight: bold;
  line-height: 27px;

  &:nth-child(1) {
    margin-right: 1em;
  }

  span:nth-child(1) {
    position: absolute;
    left: -80px;
  }

  &:hover {
    padding-left: 69px;
    background-position: 5px center;
    transform: scale(1, 1);

    span:nth-child(1) {
      left: 30px;
    }
  }
}

给“下载”设置负的left用于将其移除视界范围

鼠标悬浮时设置padding-left使按钮给“下载”留出空间

left: 30px;transform: scale(1, 1);把“下载”拉回按钮中(这个很 hack)

最后设定过渡动画即可看到流畅的过渡效果了

结构与布局

圣杯布局

目的:实现圣杯布局(左中右三列,左右两列定宽,中间列自适应宽度)

预览

<div class="g-container">
  <div class="g-left">left</div>
  <div class="g-middle">middle</div>
  <div class="g-right">right</div>
</div>
.g-container {
  display: flex;
  height: 100vh;
  min-width: 400px;

  & > div {
    text-align: center;
    color: #fff;
    line-height: 100vh;
    font-size: 3vw;
  }

  .g-left {
    order: 1;
    flex: 200px 0 0;
    background: cyan;
  }

  .g-middle {
    order: 2;
    flex: auto 1 0;
    background: purple;
  }

  .g-right {
    order: 3;
    flex: 200px 0 0;
    background: red;
  }
}

左右列的flex-grow设为200px,表示它们各占200px空间

中间列的flex-grow设为autoflex-shrink 设为 1,表明是自适应宽度

过渡与动画

动态侧边栏

目的:创建一个导航用的侧边栏,里面包含一个列表,用户鼠标浮动到链接上时会显示过渡动画

预览

<body>
  <nav>
    <ul>
      <li><a href="#">home</a></li>
      <li><a href="#">resume</a></li>
      <li><a href="#">tags</a></li>
      <li><a href="#">categories</a></li>
      <li><a href="#">archives</a></li>
      <li><a href="#">search</a></li>
    </ul>
  </nav>
</body>
nav {
  position: relative;
  background: hsl(60, 100%, 65%);
  width: 218px;
  padding-top: 5px;
}

ul {
  list-style: none;
  width: 197px;
  margin: 0 auto;
  padding: 0;
  vertical-align: baseline;
  li {
    margin: 2.5px 0;
    a {
      display: inline-block;
      position: relative;
      padding: 8px 0;
      padding-left: 20px;
      color: black;
      font-weight: 800;
      font-size: 22px;
      letter-spacing: 0.075em;
      text-decoration: none;
      text-transform: uppercase;
      &::before {
        content: "";
        position: absolute;
        opacity: 0;
        background: url("https://test.demo-1s.com/images/2019/06/24/d31DXx0KYav6cZkG.png")
          left center no-repeat;
        top: 0;
        left: 2px;
        width: 16px;
        height: 100%;
        transform: translateX(10px);
        transition: 0.3s ease-out;
      }
      &:hover::before {
        opacity: 1;
        transform: translateX(0);
      }
      &::after {
        content: "";
        position: absolute;
        height: 4px;
        width: 0;
        bottom: 2px;
        left: -3px;
        opacity: 0;
        background: white;
        border: 2px solid black;
        transition: all 0.3s cubic-bezier(0.445, 0.05, 0.55, 0.95);
      }
      &:hover::after {
        opacity: 1;
        width: calc(100% + 6px);
      }
    }
  }
}

body {
  margin: 0;
  padding: 0;
}

给 a 添加 2 个伪元素,并分别为其设置transition以及hover时的状态即可

图片幻灯片

目的:四幅图片(这里用颜色代替)按顺序依次向右滑动显示,最后被四道白色矩形依次遮住

预览

<body>
  <main id="slider">
    <div class="image"></div>
    <div class="image"></div>
    <div class="image"></div>
    <div class="image"></div>
    <div class="paint">
      <div></div>
      <div></div>
      <div></div>
      <div></div>
    </div>
  </main>
</body>
$imgs: blue, cyan, yellow, tan;

html,
body {
  margin: 0;
  padding: 0;
}

body {
  display: flex;
  min-height: 100vh;
}

#slider {
  position: relative;
  width: 500px;
  height: 300px;
  margin: auto;
}

.image {
  position: absolute;
  width: 0%;
  height: 100%;
  overflow: hidden;

  &::after {
    content: "";
    display: block;
    width: 500px;
    height: 300px;
    background-size: cover;
    background-position: center;
  }

  @for $i from 1 through length($imgs) {
    &:nth-child(#{$i})::after {
      background-color: nth($imgs, $i);
    }
  }
}

.paint {
  position: absolute;
  width: 100%;
  height: 100%;

  div {
    width: 100%;
    height: 25%;
    background-color: white;
    transform: translateX(-100%);
  }
}

// animation
@for $i from 1 to 5 {
  .image:nth-child(#{$i}) {
    animation: show-image 0.7s ease (0.5s + 0.2s * $i - 0.2s) forwards;
  }
}

@for $i from 1 to 5 {
  .paint div:nth-child(#{$i}) {
    animation: slide-right 0.5s ease (1.6s + 0.1s * $i - 0.1s) forwards;
  }
}

// keyframes
@keyframes show-image {
  from {
    width: 0%;
  }
  to {
    width: 100%;
  }
}

@keyframes slide-right {
  from {
    transform: translateX(-100%);
  }
  to {
    transform: translateX(0%);
  }
}

添加一个 slider,用flex使其垂直居中

在 slider 上添加 4 个 image,并使其大小和 slider 相同并重叠在一起,利用overflow:hidden隐藏它们

为这些 image 设置::after矩形伪元素,用作图片背景

创建show-image关键帧:元素的宽度从 0%变为 100%

为 image 创建动画:把show-image作为关键帧,每张图设置不同的延时delayfill-mode设置forwards表示动画完成时保持最后一个关键帧的属性值,这样就完成了 4 张图依次向右滑动的效果

添加一个 paint 以及 4 个子 div,表示 4 道白色矩形,默认的位置是向 x 轴左侧平移 1 个元素单位

创建slide-right关键帧:向 x 轴左侧平移 1 个元素单位变为平移 0 个单位,也就是平移到原点

为 paint 的 4 个子 div 创建动画:把slide-right作为关键帧,同样给每个矩形设置不同的延时delayforwardsfill-mode,就完成了四道白色矩形依次将图片遮住的效果

Last updated

Was this helpful?