純CSS實現(xiàn)常見的UI效果
前言
切圖仔,是大多數(shù)前端用來自嘲的稱呼。相信很多人平時寫頁面的時候,大部分時間是在切圖和排圖,如此往復(fù)。這里并不是要否定切圖本身,而是在質(zhì)疑:一直切圖到底對自己的功力增長有何好處?想想UI丟給你一套好看的界面,你卻只需一個img標(biāo)簽,或者一個background-image屬性即可搞定了它,但日后某個地方需要調(diào)整某些外觀(顏色、文字等),你還不是會讓UI再修改之前的素材,然后替換上去完事?這樣就完全受制于UI,而無法發(fā)揮自己的能動性。
那么,如何打破這個僵局?很簡單,如果你CSS玩的夠溜,你就無需再進(jìn)行那枯燥無比的切圖工作,那些界面、元素都是通過你雙手親自締造而成的,盡管創(chuàng)作它們可能會花一些功夫,但帶來的回報也是巨大的,你不僅能夠自由掌控你所創(chuàng)造出來的元素,而且能大幅提高自己的CSS功力。
在此之前
在用純CSS實現(xiàn)這些效果之前,筆者先介紹幾個常用的SCSS Mixin和一個得力武器,用它們來進(jìn)行創(chuàng)作將會事半功倍
覆蓋 - cover
- @mixin cover($top: 0, $left: 0, $width: 100%, $height: 100%) {
- position: absolute;
- top: $top;
- left: $left;
- width: $width;
- height: $height;
- }
當(dāng)你想在原先元素的基礎(chǔ)上再“復(fù)制”一個元素,并將其覆蓋在它身上時,你將會用到它
demo地址:https://codepen.io/alphardex/pen/GRjEoBZ
嵌入 - inset
- @mixin inset($inset: 0) {
- position: absolute;
- top: $inset;
- left: $inset;
- right: $inset;
- bottom: $inset;
- }
同樣地,這也是在原先元素基礎(chǔ)上復(fù)制出一個元素,只不過這個元素位置和原先的元素相同,大小會基于原先的元素而增減。
舉個例子,倘若你想創(chuàng)建多個半徑不同的同心圓,這個Mixin將會很有幫助
aqua.css
aqua.css是筆者開源的一個優(yōu)雅的、輕量級的CSS框架。里面有很多常用的組件以及常用的樣式類,用它來寫CSS體驗將會非常爽
在codepen上,筆者準(zhǔn)備了一個aqua.css模版,大家可以用它來進(jìn)行CSS的創(chuàng)作
常見UI效果
條紋效果
2
首先,我們要抓住“邊框”這個詞,如何創(chuàng)作出一個特殊的邊框呢?如果一般的CSS屬性實現(xiàn)不了的話,可以考慮用偽元素來實現(xiàn),思路如下:在原先的元素下方創(chuàng)建一個有條紋背景的偽元素,并保證原先元素覆蓋住它就行,這樣就模擬了邊框的效果。
那么如何創(chuàng)建條紋背景呢?這里我們將使用repeating-linear-gradient來實現(xiàn)它
- <div class="card w-80">
- <div class="border-stripe rounded-xl">
- Lorem ipsum...
- </div>
- </div>
- .border-stripe {
- --stripe-width: 0.5rem;
- --stripe-deg: -45deg;
- --stripe-color-1: var(--grey-color-1);
- --stripe-offset-1: 2px;
- --stripe-color-2: var(--skin-color-2);
- --stripe-offset-2: 1rem;
- --stripe-radius: 15px;
- --stripe-inset: calc(var(--stripe-width) * -1);
- &::before {
- @include inset(var(--stripe-inset));
- content: "";
- z-index: -1;
- background: repeating-linear-gradient(
- var(--stripe-deg),
- var(--stripe-color-1) 0 var(--stripe-offset-1),
- var(--stripe-color-2) 0 var(--stripe-offset-2)
- );
- border-radius: var(--stripe-radius);
- }
- }
為了保證復(fù)用性,這里將其抽象成了border-stripe類,里面的值都可以通過CSS變量來動態(tài)調(diào)節(jié)
demo地址:https://codepen.io/alphardex/pen/VwKWvdG
光澤效果
一看到光澤,相信你可能會想到一個關(guān)鍵角色——徑向漸變,通過它,我們可以創(chuàng)作出放射狀的圖案,而光澤也恰好是放射狀的,再根據(jù)背景可以疊加的特性,光澤效果就能輕松實現(xiàn)了
- <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 1</span>
- </span>
- <span class="btn btn-info btn-round btn-depth inline-flex">
- <span class="font-bold">Shine Button 2</span>
- </span>
- </div>
- :root {
- --blue-color-1: #08123d;
- --gold-color-1: #dcb687;
- --brown-color-1: #50301f;
- --brown-color-2: #936237;
- --gold-grad-1: radial-gradient(
- circle at 50% 5%,
- #{transparentize(white, 0.5)},
- #eba262
- ),
- #eba262;
- --gold-grad-2: linear-gradient(88deg, #e7924e 0%, #f8ffee 50%, #e7924e 100%);
- --blue-grad-1: radial-gradient(
- circle at 50% 5%,
- #{transparentize(white, 0.8)},
- #091344
- ),
- #091344;
- --primary-color: var(--blue-grad-1);
- --info-color: var(--gold-grad-1);
- }
- .btn {
- &-primary {
- border: 4px solid var(--gold-color-1);
- span {
- background-image: var(--gold-grad-2);
- }
- }
- &-info {
- color: var(--brown-color-1);
- border: none;
- }
- &-depth {
- box-shadow: 0 -5px 0 var(--brown-color-2);
- }
- }
demo地址:https://codepen.io/alphardex/details/vYXZNez
不規(guī)則形狀
首先,讓我們先觀察一下上圖的緞帶形狀是由哪些基本形狀組成的:中間是一個矩形,矩形下方有2個三角形,左右2側(cè)各有一個被裁切過的矩形。一提裁切,就能想到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-1: var(--yellow-color-1);
- --ribbon-color-2: var(--yellow-color-2);
- --ribbon-color-3: var(--yellow-color-3);
- position: relative;
- padding: 0.5rem 1rem;
- color: white;
- background: var(--ribbon-color-1);
- .block {
- &:nth-child(1),
- &:nth-child(2) {
- position: absolute;
- bottom: -20%;
- width: 20%;
- height: 20%;
- background: var(--ribbon-color-2);
- clip-path: polygon(0 0, 100% 100%, 100% 0);
- }
- &:nth-child(1) {
- left: 0;
- }
- &:nth-child(2) {
- right: 0;
- transform: scaleX(-1);
- }
- &:nth-child(3),
- &:nth-child(4) {
- position: absolute;
- z-index: -1;
- top: 20%;
- width: 40%;
- height: 100%;
- background: var(--ribbon-color-3);
- clip-path: polygon(0 0, 25% 50%, 0 100%, 100% 100%, 100% 0);
- }
- &:nth-child(3) {
- left: -20%;
- }
- &:nth-child(4) {
- right: -20%;
- transform: scaleX(-1);
- }
- }
- }
注意到有一行代碼transform: scaleX(-1);,這起到了水平翻轉(zhuǎn)的作用,它可以防止再寫一遍clip-path
demo地址:https://codepen.io/alphardex/pen/OJRvaaR
浮雕效果
通過仔細(xì)觀察,你會發(fā)現(xiàn)這是由2個同心的元素組成的,于是自然就想到了inset這個Mixin。
創(chuàng)建了2個同心元素后,就要想辦法來創(chuàng)建它們的浮雕光澤了。這里的光澤可以用box-shadow來實現(xiàn),通過疊加多重陰影,我們就能模擬出浮雕的效果了
- <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-1: linear-gradient(
- to right,
- var(--red-color-1) 50%,
- var(--red-color-2) 0
- );
- }
- .embossed {
- --emboss-radius: 1rem;
- --emboss-out: 6px;
- --emboss-out-minus: calc(var(--emboss-out) * -1);
- --emboss-inset: 2px;
- --emboss-inset-minus: calc(var(--emboss-inset) * -1);
- --emboss-blur: 1px;
- --emboss-bg-1: var(--red-color-3);
- --emboss-bg-2: var(--green-color-1);
- --emboss-color-1: white;
- --emboss-color-2: var(--red-color-4);
- --emboss-color-3: var(--green-color-2);
- position: relative;
- box-sizing: border-box;
- white-space: nowrap;
- &::before {
- @include inset(var(--emboss-out-minus));
- content: "";
- background: var(--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-radius: calc(var(--emboss-radius) + var(--emboss-out));
- }
- &::after {
- @include inset;
- @include flex-center;
- content: attr(data-text);
- color: white;
- font-weight: bold;
- background: var(--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-radius: var(--emboss-radius);
- }
- }
demo地址:https://codepen.io/alphardex/pen/poEEERM?editors=0110
課后作業(yè)
嘗試用純CSS來實現(xiàn)下圖的效果,不準(zhǔn)切圖哦~
我的方案:https://codepen.io/alphardex/pen/gOweBBE