纯CSS实现常见的UI,多么朴实无华的CSS3

前端人

共 8036字,需浏览 17分钟

 ·

2021-01-08 09:44


关注公众号 前端人,回复“加群

添加无广告优质学习群

前言

相信很多人平时写页面的时候,大部分时间是在切图和排图,如此往复。这里并不是要否定切图本身,而是在质疑:

一直切图到底对自己的功力增长有何好处?想想UI丢给你一套好看的界面,你却只需一个img标签,或者一个background-image属性即可搞定了它,但日后某个地方需要调整某些外观(颜色、文字等),你还不是会让UI再修改之前的素材,然后替换上去完事?这样就完全受制于UI,而无法发挥自己的能动性。

那么,如何打破这个僵局?很简单,如果你CSS玩的够溜,你就无需再进行那枯燥无比的切图工作,那些界面、元素都是通过你双手亲自缔造而成的,尽管创作它们可能会花一些功夫,但带来的回报也是巨大的,你不仅能够自由掌控你所创造出来的元素,而且能大幅提高自己的CSS功力。

在此之前

在用纯CSS实现这些效果之前,笔者先介绍几个常用的SCSS Mixin和一个得力武器,用它们来进行创作将会事半功倍 覆盖 - cover

@mixin cover($top: 0, $left: 0, $width: 100%, $height: 100%) {
  positionabsolute;
  top: $top;
  left: $left;
  width: $width;
  height: $height;
}

当你想在原先元素的基础上再“复制”一个元素,并将其覆盖在它身上时,你将会用到它

demo地址:https://codepen.io/alphardex/pen/GRjEoBZ 嵌入 - inset

@mixin inset($inset: 0) {
  positionabsolute;
  top: $inset;
  left: $inset;
  right: $inset;
  bottom: $inset;
}

同样地,这也是在原先元素基础上复制出一个元素,只不过这个元素位置和原先的元素相同,大小会基于原先的元素而增减。举个例子,倘若你想创建多个半径不同的同心圆,这个Mixin将会很有帮助

aqua.css

aqua.css是笔者开源的一个优雅的、轻量级的CSS框架。里面有很多常用的组件以及常用的样式类,用它来写CSS体验将会非常爽 在codepen上,笔者准备了一个aqua.css模版,大家可以用它来进行CSS的创作 常见UI效果 条纹效果

demo地址:https://codepen.io/alphardex/pen/VwKWvdG

首先,我们要抓住“边框”这个词,如何创作出一个特殊的边框呢?如果一般的CSS属性实现不了的话,可以考虑用伪元素来实现,思路如下:在原先的元素下方创建一个有条纹背景的伪元素,并保证原先元素覆盖住它就行,这样就模拟了边框的效果。那么如何创建条纹背景呢?这里我们将使用repeating-linear-gradient来实现它

<div class="card w-80">
  <div class="border-stripe rounded-xl">
    Lorem ipsum...
  div>
div>
.border-stripe {
  --stripe-width0.5rem;
  --stripe-deg: -45deg;
  --stripe-color-1var(--grey-color-1);
  --stripe-offset-12px;
  --stripe-color-2var(--skin-color-2);
  --stripe-offset-21rem;
  --stripe-radius15px;
  --stripe-insetcalc(var(--stripe-width) * -1);

  &::before {
    @include inset(var(--stripe-inset));
    content"";
    z-index: -1;
    backgroundrepeating-linear-gradient(
      var(--stripe-deg),
      var(--stripe-color-10 var(--stripe-offset-1),
      var(--stripe-color-20 var(--stripe-offset-2)
    );
    border-radiusvar(--stripe-radius);
  }
}

为了保证复用性,这里将其抽象成了border-stripe类,里面的值都可以通过CSS变量来动态调节 光泽效果

demo地址:https://codepen.io/alphardex/details/vYXZNez

一看到光泽,相信你可能会想到一个关键角色——径向渐变,通过它,我们可以创作出放射状的图案,而光泽也恰好是放射状的,再根据背景可以叠加的特性,光泽效果就能轻松实现了

<div class="flex flex-col space-y-4">
  <span class="btn btn-primary btn-round inline-flex">
    <span class="font-bold text-grad">Shine Button 1span>
  span>
  <span class="btn btn-info btn-round btn-depth inline-flex">
    <span class="font-bold">Shine Button 2span>
  span>
div>
:root {
  --blue-color-1#08123d;
  --gold-color-1#dcb687;
  --brown-color-1#50301f;
  --brown-color-2#936237;
  --gold-grad-1radial-gradient(
      circle at 50% 5%,
      #{transparentize(white, 0.5)},
      #eba262
    ),
    #eba262;
  --gold-grad-2linear-gradient(88deg#e7924e 0%, #f8ffee 50%, #e7924e 100%);
  --blue-grad-1radial-gradient(
      circle at 50% 5%,
      #{transparentize(white, 0.8)},
      #091344
    ),
    #091344;
  --primary-colorvar(--blue-grad-1);
  --info-colorvar(--gold-grad-1);
}

.btn {
  &-primary {
    border4px solid var(--gold-color-1);

    span {
      background-imagevar(--gold-grad-2);
    }
  }

  &-info {
    colorvar(--brown-color-1);
    border: none;
  }

  &-depth {
    box-shadow0 -5px 0 var(--brown-color-2);
  }
}

不规则形状

demo地址:https://codepen.io/alphardex/details/vYXZNez

首先,让我们先观察一下上图的缎带形状是由哪些基本形状组成的:中间是一个矩形,矩形下方有2个三角形,左右2侧各有一个被裁切过的矩形。一提裁切,就能想到clip-path这个属性,于是问题也就很好解决了

<div class="ribbon">
  Pure CSS Ribbon
  <div class="block">div>
  <div class="block">div>
  <div class="block">div>
  <div class="block">div>
div>
.ribbon {
  --ribbon-color-1var(--yellow-color-1);
  --ribbon-color-2var(--yellow-color-2);
  --ribbon-color-3var(--yellow-color-3);

  position: relative;
  padding0.5rem 1rem;
  color: white;
  backgroundvar(--ribbon-color-1);

  .block {
    &:nth-child(1),
    &:nth-child(2) {
      position: absolute;
      bottom: -20%;
      width20%;
      height20%;
      backgroundvar(--ribbon-color-2);
      clip-pathpolygon(0 0100% 100%100% 0);
    }

    &:nth-child(1) {
      left0;
    }

    &:nth-child(2) {
      right0;
      transformscaleX(-1);
    }

    &:nth-child(3),
    &:nth-child(4) {
      position: absolute;
      z-index: -1;
      top20%;
      width40%;
      height100%;
      backgroundvar(--ribbon-color-3);
      clip-pathpolygon(0 025% 50%0 100%100% 100%100% 0);
    }

    &:nth-child(3) {
      left: -20%;
    }

    &:nth-child(4) {
      right: -20%;
      transformscaleX(-1);
    }
  }
}

注意到有一行代码transform: scaleX(-1);,这起到了水平翻转的作用,它可以防止再写一遍clip-path 浮雕效果

demo地址:https://codepen.io/alphardex/pen/poEEERM?editors=0110

通过仔细观察,你会发现这是由2个同心的元素组成的,于是自然就想到了inset这个Mixin。创建了2个同心元素后,就要想办法来创建它们的浮雕光泽了。这里的光泽可以用box-shadow来实现,通过叠加多重阴影,我们就能模拟出浮雕的效果了

<div class="px-6 py-2 text-xl embossed cursor-pointer" data-text="浮雕按钮" style="--emboss-radius: 1.5rem">
  浮雕按钮
div>
:root {
  --red-color-1#af2222;
  --red-color-2#c1423e;
  --red-color-3#c62a2a;
  --red-color-4#951110;
  --green-color-1#486433;
  --green-color-2#2b361a;
  --red-grad-1linear-gradient(
    to right,
    var(--red-color-150%,
    var(--red-color-20
  );
}

.embossed {
  --emboss-radius1rem;
  --emboss-out6px;
  --emboss-out-minuscalc(var(--emboss-out) * -1);
  --emboss-inset2px;
  --emboss-inset-minuscalc(var(--emboss-inset) * -1);
  --emboss-blur1px;
  --emboss-bg-1var(--red-color-3);
  --emboss-bg-2var(--green-color-1);
  --emboss-color-1: white;
  --emboss-color-2var(--red-color-4);
  --emboss-color-3var(--green-color-2);

  position: relative;
  box-sizing: border-box;
  white-space: nowrap;

  &::before {
    @include inset(var(--emboss-out-minus));
    content"";
    backgroundvar(--emboss-bg-1);
    box-shadow: inset var(--emboss-inset-minus) var(--emboss-inset-minus)
        var(--emboss-blur) var(--emboss-color-1),
      inset var(--emboss-inset) var(--emboss-inset) var(--emboss-blur)
        var(--emboss-color-2);
    border-radiuscalc(var(--emboss-radius) + var(--emboss-out));
  }

  &::after {
    @include inset;
    @include flex-center;
    contentattr(data-text);
    color: white;
    font-weight: bold;
    backgroundvar(--emboss-bg-2);
    box-shadow: inset var(--emboss-inset) var(--emboss-inset) var(--emboss-blur)
        var(--emboss-color-1),
      inset var(--emboss-inset-minus) var(--emboss-inset-minus)
        var(--emboss-blur) var(--emboss-color-3);
    border-radiusvar(--emboss-radius);
  }
}

3D条纹描边按钮

demo地址:https://codepen.io/alphardex/pen/gOweBBE

<div class="btn btn-primary btn-round btn-3d-stripe leading-snug">
  <span class="text-stroke text-stroke-red-1 text-2xl font-bold whitespace-no-wrap" data-text="3D条纹描边按钮">3D条纹描边按钮span>
  <div class="stripe-border">div>
div>
<div class="btn btn-primary btn-round btn-3d-stripe leading-snug">
  <span class="text-stroke text-stroke-red-1 text-2xl font-bold whitespace-no-wrap" data-text="3D条纹描边按钮">3D条纹描边按钮span>
  <div class="stripe-border">div>
div>
@mixin cover($top: 0, $left: 0, $width: 100%, $height: 100%) {
  positionabsolute;
  top: $top;
  left: $left;
  width: $width;
  height: $height;
}

@mixin inset($inset: 0) {
  positionabsolute;
  top: $inset;
  left: $inset;
  right: $inset;
  bottom: $inset;
}

:root {
  --orange-color-1#fead54;
  --orange-color-2#ff9e51;
  --red-color-1#5f1717;
  --red-color-2#f6566d;
  --red-color-3#ffe9f0;
  --yellow-color-1#fee64d;
  --polka-bgradial-gradient(var(--orange-color-220%, transparent 00 0 /
      30px 30px,
    radial-gradient(var(--orange-color-220%, transparent 015px 15px / 30px
      30px,
    linear-gradient(var(--orange-color-1), var(--orange-color-1)) 0 0 / 100%;
  --primary-colorvar(--yellow-color-1);
}

.text-stroke {
  --stroke-width5px;

  position: relative;
  color: transparent;

  &::before,
  &::after {
    @include cover;
    contentattr(data-text);
    color: white;
  }

  &::before {
    z-index0;
    -webkit-text-strokevar(--stroke-width) var(--stroke-color);
  }

  &::after {
    z-index1;
  }
}

.text-stroke-red-1 {
  --stroke-colorvar(--red-color-1);
}

.stripe-border {
  --stripe-width0.5rem;
  --stripe-deg45deg;
  --stripe-offset-12px;
  --stripe-offset-21rem;
  --stripe-insetcalc(var(--stripe-width) * -1);

  &::before {
    @include inset(var(--stripe-inset));
    content"";
    z-index: -1;
    backgroundrepeating-linear-gradient(
      var(--stripe-deg),
      var(--stripe-color-10 var(--stripe-offset-1),
      var(--stripe-color-20 var(--stripe-offset-2)
    );
    border-radiusvar(--stripe-radius);
  }
}

.btn {
  --btn-padding0.35rem 1.25rem;

  &-3d-stripe {
    --stripe-color-1var(--red-color-1);
    --stripe-color-2var(--red-color-2);
    --btn-bg-2var(--red-color-3);
    --stripe-radius30px;

    border3px solid var(--stripe-color-1);
    box-shadow0 0 0 6px var(--btn-bg-2), 0 0 0 9px var(--stripe-color-1);

    .stripe-border {
      @include cover(0.06rem, 0.03rem, calc(100% + 9px), calc(100% + 9px));

      &::before {
        border3px solid var(--stripe-color-1);
      }
    }
  }
}

原文地址:juejin.cn/post/6914444370033213448



1.如果看到这里,说明你喜欢这篇文章,请 点赞在看

2.关注公众号前端人,回复资料包领取我整理的前端进阶资料包

3.回复加群,加入前端进阶群,和小伙伴一起学习讨论!


浏览 21
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报