4.5 顆星

前言

今天我來說述一則故事。css

話很少說,今天的故事與一張圖有關:html

看到了沒,閃閃的 4.5 顆星。ios

前些天某位大佬在演示這閃閃的 4.5 顆星實現的時候,我不經意地瞟了一眼代碼。嘴角些許上揚:呵,竟然用的是圖片來實現的,水平看來不咋地!要是換作我,確定 N 種方法!git

而後我就開始認真的想了想這 N 種方法到底有哪幾種。。。github


我首先想的是:圖片多 low 啊,還不如 css 畫的呢!web

用 CSS 畫出來

在一頓胡思亂想以後,最終決定用一個 CSS icon 庫ioniconsapp

立馬寫下了以下代碼:ionic

<div class="containers">
  <div class="css-only">
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star-half"></i></div>
  </div>
</div>
複製代碼
.css-only {
  display: flex;
  color: rgb(255, 172, 45);
}
.css-only .star {
  width: 2rem;
  height: 2rem;
  padding: 0.5rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
複製代碼

這裏的每顆星都是由 CSS 畫出來的,最後那半顆也是,類名不一樣罷了。svg

等我寫完這段代碼以後,我忽然的趕忙彷佛和咱們想要實現的效果有那麼一點不同:最後那半顆星的顏色不一樣。post

第一次升級

<div class="containers">
  <div class="double-1">
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
  </div>
  <div class="double-2">
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
  </div>
</div>
複製代碼
.double-1,
.double-2 {
  display: flex;
}
.double-1 .star,
.double-2 .star {
  width: 2rem;
  height: 2rem;
  padding: 0.5rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  flex-shrink: 0;
}
.double-1 {
  color: rgb(218, 218, 218);
}
.double-2 {
  position: absolute;
  top: 0;
  left: 0;
  width: 13.5rem;
  overflow: hidden;
  color: rgb(255, 172, 45);
}
複製代碼

在寫完代碼以後看了看,嗯,感受很滿意。可是越看越以爲這和放幾張圖片沒啥兩樣。

使用-webkit-background-clip

先簡單的介紹一下,-webkit-background-clip 是用來設置背景的範圍的,若是讀者有疑惑能夠參考個人上一篇文章:CSS3 的一對孿生兄弟之 background & mask

既然想要裝逼,那必須用一些通常人不會用的屬性,這樣才能顯得頗有能耐!

<div class="containers">
  <p class="bgClip">
    <span class="star"></span><span class="star"></span ><span class="star"></span><span class="star"></span ><span class="star"></span>
  </p>
</div>
複製代碼
.bgClip {
  display: flex;
  background-image: -webkit-gradient(
    linear,
    0 50%,
    100% 50%,
    from(rgb(255, 172, 45)),
    color-stop(0.9, rgb(255, 172, 45)),
    color-stop(0.9, rgb(218, 218, 218)),
    to(rgb(218, 218, 218))
  );
  -webkit-background-clip: text;
  color: transparent;
}
.bgClip span {
  text-align: center;
  width: 2rem;
  height: 2rem;
  padding: 0.5rem;
}
複製代碼

經過設定 -webkit-background-clip: text;讓背景只存在於文本之上。且將文本顏色設置爲透明,這時候背景的顏色就會呈現出來。背景咱們用一個顏色漸變去實現。

這種方法有一個小小的缺陷,很是依賴文本表情符號,一旦不是星星或者要求換成別的符號,有可能就實現不了。

background 的孿生兄弟 mask

mask 能夠給容器添加遮蓋,若是讀者有疑惑能夠參考個人上一篇文章:CSS3 的一對孿生兄弟之 background & mask

<div class="containers">
  <div class="mask"></div>
</div>
複製代碼
.mask {
  display: flex;
  width: 15rem;
  height: 3rem;
  background-image: -webkit-gradient(
    linear,
    0 50%,
    100% 50%,
    from(rgb(255, 172, 45)),
    color-stop(0.9, rgb(255, 172, 45)),
    color-stop(0.9, rgb(218, 218, 218)),
    to(rgb(218, 218, 218))
  );
  -webkit-mask-image: url(../svg/五角星.svg);
  -webkit-mask-size: 3rem;
  -webkit-mask-repeat: repeat-x;
}
複製代碼

我先給容器設置呢寬高和背景漸變色,而後經過設置遮罩圖形爲五角星,且沿 X 軸平鋪,讓背景色從遮罩圖形中透出來,最終實現了效果!

可是這也有一個很差的地方,那就是遮罩圖形很依賴於美工小姐姐的設計,咱們無法控制兩個小星星之間的距離,由於平鋪是沒有間隙的。若是美工小姐姐給咱們的五角星的留白不多,咱們的小星星就會連在一塊兒,會很醜!

mix-blend-mode

mix 和 blend 的中文意譯均爲混合,那麼這個屬性的做用直譯過來就是混合混合模式。mix-blend-mode 描述了元素的內容應該與元素的直系父元素的內容和元素的背景如何混合。

<div class="containers">
  <div class="mbmContent">
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
    <div class="star"><i class="icon ion-ios-star"></i></div>
  </div>
  <div class="mbmScore"></div>
</div>
複製代碼
.mbmContent {
  width: 15rem;
  height: 3rem;
  display: flex;
  color: rgb(0, 0, 0);
  background-color: #fff;
}
.mbmScore {
  position: absolute;
  top: 0;
  left: 0;
  width: 15rem;
  height: 3rem;
  background-image: -webkit-gradient(
    linear,
    0 50%,
    100% 50%,
    from(rgb(255, 172, 45)),
    color-stop(0.9, rgb(255, 172, 45)),
    color-stop(0.9, rgb(218, 218, 218)),
    to(rgb(218, 218, 218))
  );
  mix-blend-mode: lighten;
}
.mbmContent .star {
  width: 2rem;
  height: 2rem;
  padding: 0.5rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
複製代碼

在這裏,我將星星的顏色設置爲了黑色,其父容器.mbmContent 的背景顏色爲白色。我同時讓.score 容器的脫離文檔流且與.mbmContent 重合,設置漸變顏色。經過設置 mix-blend-mode: lighten,可讓.containers 這一父容器中的背景顏色以 lighten 方式混合,具體如何混合,這裏再也不熬述,讀者如有興趣,能夠自行查閱資料。

後記

在寫完這五種方法以後,總要評一評哪一個是最好的方法。首先排除第一種,第三種和第四種。由於以上這幾種咱們在實現的時候都說明了各自的缺點。

對於第五種其實也是有缺點的:

當咱們在外層容器設置一個背景顏色的時候,第五種缺點就暴露了。

<div class="wrapper">
  <!-- 在最外層包裹一個容器 -->
</div>
複製代碼
.wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  background-color: lightgreen;
}
.containers {
  width: 15rem;
  height: 3rem;
  border: 1px solid red;
  position: relative;
}
複製代碼

因爲第五種方法須要設置五角星容器的背景色爲白色,因此當最外層設置了背景色的時候,會顯得特別突兀,不協調。

由此能夠得出,最棒的方法是第二種!

可是,寫到這裏不得不說直接用圖片代替樣式,可讓功能的實現變得更簡單。可是假若我想讓星星顏色的填充能夠動畫的形式顯示,或者每 0.1 分之差都體現出來的話,我以爲這時候第二種 方法應該是最棒的選擇。


筆者專門在 github 上建立了一個倉庫,用於記錄平時學習全棧開發中的技巧、難點、易錯點,歡迎你們點擊下方連接瀏覽。若是以爲還不錯,就請給個小星星吧!👍


2019/04/06

AJie

相關文章
相關標籤/搜索