天天看點

聊一聊CSS的過去與未來,加深對CSS的了解

作者:前端達人
轉載說明:原創不易,未經授權,謝絕任何形式的轉載
聊一聊CSS的過去與未來,加深對CSS的了解

很久以前,CSS就像一陣清新的氣息,隻需簡單輕松地為頁面添加樣式。

它涉及設定規則,讓浏覽器自動處理。你可以改變邊距、字型和大小,但這隻是淺嘗辄止,你懂的嗎?

真正的亮點是那個"級聯"的特性,允許樣式繼承和覆寫其他樣式,創造出一些動态、酷炫的頁面。快進到今天,CSS就像網頁設計的瑞士軍刀。它具備了使用彈性盒子和網格來實作動畫、轉換和适應布局的能力,使得網頁變得響應式和酷炫。

從基本樣式到複雜動畫,CSS已經發展到了一個全新的層次。它不再隻是簡單的樣式設定,而是讓你的整個網頁煥發生機。

讓我們深入了解CSS是如何發展至今的(或者直接滾動到最後一節,展望未來…)。

CSS選擇器——樣式的不斷演變之路

CSS選擇器就像标簽遊戲中的精确指令。它是一條規則,用于識别需要樣式化的HTML元素。無論你是指向一個<div>、.class還是#id,選擇器都是你的樣式聲明的信使,確定正确的元素被"标記"。讓我帶你回到CSS的早期時代。那是一個網頁設計新鮮、原始,而且在很多方面都有限制的時代。還記得舊的HTML标簽,比如font和center嗎?我們使用它們是因為我們必須這樣做,而不是因為我們想這樣做。然後,就像90年代漫畫書中的超級英雄一樣,CSS出現了,它帶來了選擇器的力量。最初的CSS選擇器和它們所應用的HTML一樣基本:

h1 {
  color: blue;
}           

那時的選擇器簡單、有效,但非常有限。這就像用蠟筆繪制西斯廷教堂一樣。

為了增加更多的靈活性,CSS2引入了新的選擇器,比如子元素選擇器(>)、相鄰兄弟選擇器(+)和屬性選擇器([attr=value])。這些選擇器可以實作更精确的樣式化:

/* Child Selector */
div > p {
  color: red;
}

/* Adjacent Sibling Selector */
h1 + p {
  margin-top: 20px;
}

/* Attribute Selector */
input[type="text"] {
  width: 200px;
}           

這些選擇器讓我們能夠表達元素之間更複雜的關系,使我們的樣式表更高效和有組織。這是一個進步,但我們仍然需要更多。

然後出現了CSS3。它通過更強大的工具擴充了CSS選擇器的能力,例如通用兄弟組合器(~)、:not()僞類以及一系列的屬性選擇器:

/* General Sibling Combinator */
h1 ~ p {
  font-size: 1.2em;
}

/* :not() Pseudo-class */
div:not(.highlighted) {
  opacity: 0.5;
}

/* Attribute Selectors */
a[href*="google"] {
  background: url(/images/google-icon.png) no-repeat;
}
           

我們不再隻是對元素進行樣式設定,而是與它們互動,探索它們的屬性,它們之間的關系。我們開始打造複雜的設計,能夠根據内容的結構和含義進行響應式布局。

聊一聊CSS的過去與未來,加深對CSS的了解

CSS3帶來了僞類,如:nth-child、:nth-of-type、:checked,以及僞元素::before和::after。我們的蠟筆已經變成了一個完整的藝術家調色闆,而Web的畫布也是以變得更加豐富多彩。

/* :nth-child Selector */
li:nth-child(odd) {
  background: lightgray;
}

/* :checked Pseudo-class */
input[type="checkbox"]:checked {
  border-color: green;
}

/* ::before and ::after Pseudo-elements */
blockquote::before {
  content: "❝";
  font-size: 3em;
}
blockquote::after {
  content: "❞";
  font-size: 3em;
}
           

還值得一提的選擇器是僞類:is。它允許你将多個選擇器組合在一條語句中,減少代碼的重複性,提高可讀性。如果你想深入了解,請查閱Steve的文章《Simpler CSS Selectors With :is()》。

最後還有一個提到的選擇器是:where,它與:is類似。然而,關鍵的差別在于:where的特異性始終為0。

選擇器為我們提供了在代碼中表達創意願景的工具。它們不斷演進,推動着Web進入設計的更加令人興奮的前沿。

級聯——利用特異性和繼承

級聯是CSS的一個關鍵特性,當正确利用時,可以使你的樣式表更高效、更易于維護。它指的是将不同的樣式表結合起來,并解決适用于同一進制素的不同CSS規則之間的沖突。

這裡的特異性概念發揮了關鍵作用。ID選擇器的特異性高于類選擇器,類選擇器的特異性高于類型選擇器。

#header {
  color: blue; /* This will apply because ID selectors have the highest specificity */
}

.container .header {
  color: red; /* This won't apply to the element with id "header" */
}

header {
  color: green; /* This won't apply to the element with id "header" */
}           

了解如何與級聯一起工作,而不是對抗它,将能夠避免許多問題。使用特異性電腦等工具可以大有裨益。

媒體查詢的靈活性

媒體查詢是CSS的一個關鍵優勢,它提供了内置的響應式設計能力。媒體查詢幫助你針對不同的裝置或螢幕寬度應用不同的樣式。這種靈活性使得你能夠根據不同的裝置特性和螢幕尺寸進行定制化的樣式設定。

@media only screen and (max-width: 600px) {
  body {
    background-color: lightblue;
  }
}           

在這個例子中,當螢幕寬度小于或等于600px時,body的背景色會變成淺藍色。這使得CSS在建立響應式設計中扮演着重要的角色。

讓我們回顧一下CSS中的媒體查詢是如何保持新鮮的:

  • 1994年:我們的主要人物Håkon Wium Lie提出了媒體查詢的第一個想法。這是一項重大的開端!
  • 1998年:CSS2登場,為我們帶來了第一次媒體查詢的體驗。
  • 2001年:CSS3亮相,通過一些新功能使媒體查詢更新。
  • 2012年:媒體查詢大放異彩!它們成為W3C推薦的标準。

現在:媒體查詢在所有主要的浏覽器中都得到支援,并成為響應式網頁設計中的關鍵工具。

動畫和過渡的強大能力

通過CSS3,動畫和過渡已成為現代網頁的重要組成部分,創造了動态的使用者體驗。你可以在一段時間内使CSS屬性發生變化,控制過渡的速度,并建立基于關鍵幀的動畫效果。

button {
  transition: background-color 0.5s ease;
}

button:hover {
  background-color: blue;
}           

在這段代碼中,當你将滑鼠懸停在按鈕上時,它的背景色會在半秒鐘的時間内過渡到藍色。

擁抱CSS變量的魔力(自定義屬性)

自1997年成立以來,CSS工作組就意識到了對CSS變量的需求。到了2000年代末,開發人員已經創造了各種解決方案,如自定義PHP腳本和預處理器(如Less和Sass),以彌補這個缺陷。

意識到内置的解決方案将簡化這個過程,該組在2012年釋出了CSS變量子產品的第一個草案。在2017年,它更名為層疊變量的CSS自定義屬性,并得到了廣泛的浏覽器支援。

過去,更新CSS值是一項手動、耗時的工作,靜态CSS的時代已經過去了。現在,我們的工具包中有了CSS變量,可以在整個樣式表中存儲和重用特定的值。這些變量確定一緻性,并使更新變得輕而易舉。

以下是CSS變量的一些示例:

:root {
  --brand-color: #32a852;
}

body {
  background-color: var(--brand-color);
}

/* On hovering over the body, the brand color changes */
body:hover {
  --brand-color: #a83258;
}
           

将滑鼠懸停在頁面上,瞧!你的網站樣式完全變了個樣。這就是CSS變量的威力!

曆代布局

多年來,CSS布局經曆了許多變化。開發人員過去常常使用表格和浮動來建立布局,但這種方式難以維護,而且不太适應響應式設計。後來,媒體查詢、彈性盒子和網格布局的引入徹底改變了開發人員建立布局的方式,使其更具響應性和易于維護。讓我們深入了解一下。

擺脫基于表格的布局,轉向CSS

進入21世紀初,基于表格的布局時代開始逐漸消退。還記得那些時光嗎?當我們使用table、tr和td來安排頁面上的一切,甚至連布局都是如此。啊,那些日子真是美好!

<table>
  <tr>
    <td>Header</td>
  </tr>
  <tr>
    <td>Main Content</td>
    <td>Sidebar</td>
  </tr>
  <tr>
    <td>Footer</td>
  </tr>
</table>           

那是一個我們迫使HTML按照我們的意願彎曲的時代,将其用于并非原本意圖的用途——布局。但嘿,我們讓它發揮作用了,對吧?但讓我們真實一點,那是一種痛苦。代碼難以維護,可通路性受到了影響,響應式設計也隻是一個遙遠的夢想。我們需要一種改變,而CSS就是那個改變!

浮動布局的時代以及clearfix的黑科技

啊,浮動布局的時代。親愛的讀者們,我幾乎可以看到你們臉上的懷舊微笑和沮喪的表情。你們知道,在flexbox出現并讓我們的生活變得輕松得多之前,我們一直被困在浮動布局的世界裡。

最初作為圍繞圖檔排列文本的簡單方法(想象報紙的版面布局),浮動成為了建立整個網頁布局的意外工具。

.column {
  float: left;
  width: 50%;
}           

就這樣,我們就有了一個雙列布局。聽起來很簡單,對吧?但問題出現在我們嘗試在浮動元素下方添加更多元素時。突然間,我們的頁腳就像自己闖蕩一樣,緊貼在DOM結構中更高的内容旁邊。哦,這個混亂!

聊一聊CSS的過去與未來,加深對CSS的了解

這是由于浮動元素的一個特殊特性導緻的。它們在正常的文檔流中被部分移除,這意味着在标記中跟随它們的元素會像浮動元素不存在一樣行為。

為了解決這個問題,我們不得不求助于我們現在親切(或不太親切)稱之為"clearfix黑科技"的方法。這個黑科技通過建立一個新的塊級格式化上下文,強制容器展開以包含浮動元素。

這是著名的clearfix黑科技,它拯救了許多布局:

.group:after {
  content: "";
  display: table;
  clear: both;
}           

通過在容器中添加一個僞元素:after,并給它設定display: table;和clear: both;,我們有效地清除了浮動。突然間,我們的頁腳回到了它們應該在的位置,一切都恢複了正常。

盡管浮動具有一些古怪和意外的行為,但掌握浮動對于每個網頁開發人員來說是一種成長的必經之路。它教會了我們了解CSS的盒子模型、文檔流以及CSS可能表現出的奇妙和奇異的方式的重要性。這是一個具有挑戰性的、有時讓人抓狂的經曆,但它是通向我們今天所熟悉和喜愛的CSS之路上的重要裡程碑。

使用flexbox和grid的全新布局

兩個最重要的改變遊戲規則的因素,極大地改進了網頁開發,它們分别是:flexbox。這兩個家夥完全颠覆了布局設計的正常。

首先是flexbox。在CSS3中引入的flexbox對于盒子的對齊、方向、順序和大小的設定是一次徹底的革命。不再需要處理浮動和定位的困擾了,大家注意啦。flexbox使得建立靈活、響應式的布局變得簡單,用更少的代碼獲得更多的控制。下面是一個簡單的代碼示例,向你展示如何使用它:

.container {
  display: flex;
  justify-content: space-between;
}

.item {
  flex: 1;
}           

在這個例子中,我們将容器設定為display: flex;,讓其子元素知道它們處于flex上下文中。justify-content: space-between;讓我們的項目之間保持良好的間距。然後我們使用flex: 1;給項目添加了相同的寬度,填滿了整個容器的空間。簡潔而簡單。

然後是grid布局,下一個重大飛躍。Grid布局在2017年左右引入,将CSS布局提升到了一個全新的水準,同時讓我們定義了列和行。CSS grid讓我們能夠建立複雜的二維布局,在之前是非常困難的。以下是一個簡單示例:

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 10px;
}

.item {
  grid-column: span 2;
}           

在這段代碼中,.container是我們的網格容器。我們使用grid-template-columns: repeat(3, 1fr);定義了三個相等寬度的列,并使用grid-gap: 10px;設定它們之間的間距為10像素。然後對于我們的項目,我們使用grid-column: span 2;使項目跨越兩列。那真是強大的功能!

如果你研究一下grid-template-areas屬性,你就可以成為真正的CSS grid專家。

還記得居中元素時的困擾嗎?不論是垂直居中還是水準居中,組合使用各種屬性如margin、position、top、left和transform,足以讓人頭暈目眩。

.container {
  position: relative;
}

.element {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}           

快進到今天,flexbox讓居中變得輕而易舉:

.container {
  display: flex;
  justify-content: center;
  align-items: center;
}           

在過去,建立複雜布局通常意味着使用浮動元素,這可能會很棘手且難以管理。以下是使用浮動元素建立雙列布局的簡化示例:

.container::after {
  content: "";
  display: table;
  clear: both;
}

.column {
  float: left;
  width: 50%;
}           

如今,借助CSS Grid,你可以用極少的代碼建立複雜的布局,而無需頭痛的困擾:

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
}           

對未來的一瞥

CSS中有幾個即将推出的功能和改進已經在網頁設計和開發社群引起了極大的關注。你可以在Chrome團隊的最新文章《CSS和UI的新特性》中找到詳細的清單。

以下是我對其中一些功能感到興奮的原因:

容器查詢

目前尚未在Firefox和Safari中支援

容器查詢使得能夠對子元素進行樣式設定,并在布局中進行布局控制。可以根據元素的可用空間來進行元素的改變,如下所示:

由于容器查詢的存在,樣式是動态的。改變視口的大小會根據每個元素的可用空間觸發相應的變化。

文法與媒體查詢有些相似,隻是你隻需定義在容器大小滿足條件時所需的樣式:

以下是實際應用的樣子:

/* Create a containment context */
.post {
  container-type: inline-size; /* size & normal are valid values as well */
}

/* Default heading styles for the card title */
.card h2 {
  font-size: 1em;
}

/* If the container is larger than 700px */
@container (min-width: 700px) {
  .card h2 {
    font-size: 2em;
  }
}           

樣式查詢

目前尚未在Firefox和Safari中支援

查詢父容器的樣式值:

<li class="card-container" style="--sunny: true;">
  <div class="weather-card">
    <div class="day">Saturday</div>
    <div class="date">February <span>12</span></div>
    <div class="temps">
      <div class="high">High: <span>55</span></div>/
      <div class="low">Low: <span>47</span></div>
    </div>
    <div class="features">
      Clear skies, sun
    </div>
  </div>
</li>

<style>

.card-container {
  container-name: weather;
}

/* In case the custom propery --sunny: true; change the child */

@container style(--sunny: true) {
 .weather-card {
   background: linear-gradient(-30deg, yellow, orange);
 }

 .weather-card:after {
   content: url(<data-uri-for-demo-brevity>);
   background: gold;
 }
}

</style>           

:has僞類

目前尚未在Firefox中支援。

根據後代元素來設定樣式的一種方法。基本上,你可以根據子元素來應用樣式,這意味着它可以作為一種理想的父選擇器。然而,你也可以在父元素内部對子元素進行樣式設定。

<article>
 <h1>Hello</h1>
 <h2>World</h2>
</article>

<style>
/* style parent according to children */
article:has(h1) {
 background: lightgray;
}

/* style child by parent content */
article:has(h1) h2 {
   color: yellow;
}

/* style sibling by adjacent element */
h1:has(+ h2) {
 color: hotpink;
}
</style>            

text-wrap: balance

目前僅在Chromium中支援

這個新值,顧名思義,将允許你平衡文本,是以你不再需要使用JS來實作。将其應用于文本塊将真正讓你的設計師開心。

聊一聊CSS的過去與未來,加深對CSS的了解

嵌套

目前尚未在Firefox中支援

最後,就像SASS和Less一樣,嵌套和共同定位與選擇器相關的樣式:

.parent {
  color: blue;

  .child {
    color: red;
  }
}           

此外,你還可以嵌套媒體查詢(和容器查詢):

.card {
  display: flex;
  gap: 1rem;

  @media (width >= 480px) {
    display: grid;
  }
}           

另外,第一個例子也可以這樣寫:

.parent {
  color: blue;

  & .child {
    color: red;
  }
}           

子網格

在Firefox和Safari中得到支援,并在Chrome的标志下使用

子網格是完善網格布局的一部分,可以将網格布局應用于網格項的子元素,進而實作更一緻和可維護的布局。通過添加grid-template-rows或grid-template-columns屬性并設定為subgrid值來使用:

<div class="grid">
  <div class="item">
    <div class="subitem"></div>
  </div>
</div>

<style>
/* some styles removed for brevity */
.grid {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-template-rows: repeat(4, minmax(100px, auto));
}

.item {
  display: grid;
  grid-column: 2 / 7;
  grid-row: 2 / 4;
  grid-template-columns: subgrid;
  grid-template-rows: subgrid;
  background-color: #ffd8a8;
}

.subitem {
  grid-column: 3 / 6;
  grid-row: 1 / 3;
  background-color: rgb(40, 240, 83); /* green */
}
</style>           
聊一聊CSS的過去與未來,加深對CSS的了解

Scoped CSS

仍處于工作草案階段,指定特定樣式适用的範圍,從本質上為CSS建立本地的命名空間:

@scope (.card) {
  /* only affects a .title that is within a .card */
  .title { 
    font-weight: bold;
  }
}           

滾動驅動的動畫

仍處于實驗階段

根據滾動容器的滾動位置控制動畫的播放。再次減少了使用JavaScript建立視差滾動、閱讀訓示器等功能的複雜性。你可以在這裡看到一些很棒的示範。

聊一聊CSS的過去與未來,加深對CSS的了解

級聯層(@layer)

現在得到了廣泛支援,在存在多個級聯層的情況下,定義了優先級的順序。您可以根據重要性對樣式表進行排序:

@layer base {
  a {
    font-weight: 800;
    color: red; /* ignored */
  }

  .link {
    color: blue; /* ignored */
  }
}

@layer typography {
  a {
    color: green; /* styles *all* links */
  }
}

@layer utilities {
  .pink {
    color: hotpink;  /* styles *all* .pink's */
  }
}           

View transitions

(在Firefox和Safari中不受支援)

允許在單個步驟中更改DOM,同時在兩個狀态之間建立動畫過渡。不再需要使用單頁應用程式(SPA)來完成此操作。

這需要一些JavaScript:

function spaNavigate(data) {
  // Fallback for browsers that don't support this API:
  if (!document.startViewTransition) {
    updateTheDOMSomehow(data);
    return;
  }

  // With a transition:
  document.startViewTransition(() => updateTheDOMSomehow(data));
}           

然後 CSS 接管:

@keyframes slide-from-right {
  from { opacity: 0; transform: translateX(75px); }
}

@keyframes slide-to-left {
  to { opacity: 0; transform: translateX(-75px); }
}

::view-transition-old(root) {
  animation: 350ms both slide-to-left ease;
}

::view-transition-new(root) {
  animation: 350ms both slide-from-right ease;
}           

結束

CSS的未來充滿了巨大的潛力,可以簡化複雜的任務,提升性能,并讓開發者建立沉浸式的體驗。

随着CSS的發展,我們可能會看到新的進階特性湧現,模糊了CSS和JavaScript之間的界限,為目前依賴于JavaScript庫的任務提供了原生解決方案。

此外,可能會出現更全面的CSS架構,利用這些新功能。

保持對最新的CSS發展的了解非常重要,因為CSS在網頁設計和開發中的重要性持續存在。關注CSS Working Group的更新、追随行業上司者,并探索浏覽器預覽中的新功能,将有助于您保持更新。

擁抱前方令人興奮的可能性,不斷學習,并積極參與塑造未來的網絡。

由于文章内容篇幅有限,今天的内容就分享到這裡,文章結尾,我想提醒您,文章的創作不易,如果您喜歡我的分享,請别忘了點贊和轉發,讓更多有需要的人看到。同時,如果您想擷取更多前端技術的知識,歡迎關注我,您的支援将是我分享最大的動力。我會持續輸出更多内容,敬請期待。