注意:我剛剛翻譯了下面的文字並將其發佈在這裡。參考文獻在本文末。
CSS 是一種高度專業化的程式語言,專注於樣式系統。由於這個單一用例及其聲明性,有時很難理解。有些人甚至否認它是一種程式語言。讓我們透過編寫一個聰明且靈活的樣式系統來證明他們是錯的。
更傳統和通用的語言(如JavaScript)為我們提供了「條件」(if/then)、「循環」(for、while)、「邏輯門」(===、&& 等)等工具. ) 和“變數”。這些結構在 CSS 中的命名不同,它們的語法也非常不同,以更好地適應文件樣式化的特定用例,其中一些結構直到幾年前才在 CSS 中可用。
變數是最直接的。它們在 CSS 中被稱為 自訂屬性(儘管每個人都稱它們為變量,甚至是他們自己的語法)。
:root { --color: red; } span { color: var(--color, blue); }
雙破折號宣告一個變數並賦值。這必須發生在一個範圍內,因為在選擇器之外執行此操作會破壞 CSS 語法。請注意 :root 選擇器,它作為全域範圍起作用。
條件可以用多種方式編寫,這取決於您想要使用它們的位置。選擇器具有其元素的範圍,媒體查詢具有全域範圍並且需要它們自己的選擇器。
[data-attr='true'] { /* if */ } [data-attr='false'] { /* elseif */ } :not([data-attr]) { /* else */ }
:checked { /* if */ } :not(:checked) { /* else */ }
:root { color: red; /* else */ } @media (min-width > 600px) { :root { color: blue; /* if */ } }
計數器是CSS中最直接的循環形式,但也是使用場景最受限的一種。您只能在內容屬性上使用計數器,將其顯示為文字。您可以在任何給定點調整“增量”、“起點”和“值”,但輸出始終僅限於文字。
main { counter-reset: section; } section { counter-increment: section; counter-reset: section; } section > h2::before { content: 'Headline ' counter(section) ': '; }
但是如果您想使用循環來定義重複佈局模式怎麼辦?這種類型的循環有點晦澀:它是網格的自動填充屬性。
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
這會用盡可能多的元素填充網格,同時縮放它們以填充可用空間,但在必要時將它們分成多行。只要找到網格項目並將其限制為最小寬度 300px 和最大寬度為其網格容器大小的一小部分,它就會重複。看到可能比解釋更容易:
最後,還有「循環選擇器」。他們接受一個參數,該參數可以是一個可以非常精確地選擇的公式。
section:nth-child(2n) { /* seleciona todos os elementos pares */ } section:nth-child(4n + 2) { /* seleciona a cada quarto items, iniciando a partir do segundo */ }
對於非常特殊的情況,您可以將 :nth-child() 與 :not() 結合使用,例如:
section:nth-child(3n):not(:nth-child(6)) { /* seleciona a cada 3 elementos, mas não o sexto elemento */ }
您可以將 :nth-child() 替換為 :nth-of-type() 和 :nth-last-of-type() 來變更最後範例的範圍。
Ana Tudor 寫了一篇關於 CSS 邏輯閘的文章。 Login Gates 致力於將變數與計算結合的想法。然後,她繼續用它來建模和動畫 3D 物件。這聽起來像是神秘的魔法,隨著文章的繼續,它會變得更加瘋狂,而且它通常是為什麼 CSS 實際上是一種程式語言的最佳解釋之一。
* + * { margin-top: 1rem; }
貓頭鷹選擇器選擇一個項目後面的每個項目。對此應用 margin-top 可以有效地增加專案之間的間隙,就像 grid-gap 一樣,但沒有網格系統。這也意味著它更具可自訂性。您可以覆蓋邊距頂部並使其適應任何類型的內容。想要每個項目之間有 1rem 的空間,但在標題之前有 3rem 的空間?使用貓頭鷹選擇器比在網格中更容易做到這一點。
Kevin Pennekamp 有一篇關於此的深入文章,甚至用偽代碼解釋了他的演算法。
Podemos criar toggles em nosso código css que ligam e desligam certas regras com variables e calc. Isso nos dá condições muito versáteis.
.box { padding: 1rem 1rem 1rem calc(1rem + var(--s) * 4rem); color: hsl(0, calc(var(--s, 0) * 100%), 80%); background-color: hsl(0, calc(var(--s, 0) * 100%), 15%); border: calc(var(--s, 0) * 1px) solid hsl(0, calc(var(--s, 0) * 100%), 80%); } .icon { opacity: calc(var(--s) * 100%); transform: scale(calc(var(--s) * 100%)); }
Dependendo do valor de --s, .box habilitará ou desabilitará seus alert styles.
Vamos levar a mesma lógica um passo adiante e criar uma color variable que depende do seu contraste com a background color:
:root { --theme-hue: 210deg; --theme-sat: 30%; --theme-lit: 20%; --theme-font-threshold: 51%; --background-color: hsl(var(--theme-hue), var(--theme-sat), var(--theme-lit)); --font-color: hsl( var(--theme-hue), var(--theme-sat), clamp(10%, calc(100% - (var(--theme-lit) - var(theme-font-threshold)) * 1000), 95%) ); }
Este snippet calcula um background color a partir de valores HSL e uma font color black ou white, invertendo o valor de lightness (luminosidade) do background. Isso por si só pode resultar em baixo contraste de cor (uma fonte cinza de 40% em um background cinza de 60% é praticamente ilegível), então subtrairei um valor threshold (o ponto em que a cor muda de white para black), multiplicarei por um valor insanamente alto como 1000 e farei clamp nele entre 10% e 95%, para obter uma porcentagem de lightness válida no final. Tudo é controlável editando as quatro variáveis no início do snippet.
Este método também pode ser usado para escrever lógica de cores intrincada e themes automáticos, com base apenas em valores HSL.
Vamos combinar o que temos até agora para limpar a stylesheet. Ordenando tudo por viewports parece um pouco espaguete, mas ordenar isso por componente não parece nada melhor. Com variables, podemos ter o melhor dos dois mundos:
/* define variables */ :root { --paragraph-width: 90ch; --sidebar-width: 30ch; --layout-s: "header header" "sidebar sidebar" "main main" "footer footer"; --layout-l: "header header" "main sidebar" "footer footer"; --template-s: auto auto minmax(100%, 1fr) auto / minmax(70%, var(--paragraph-width)) minmax(30%, var(--sidebar-width)); --template-l: auto minmax(100%, 1fr) auto / minmax(70%, var(--paragraph-width)) minmax(30%, var(--sidebar-width)); --layout: var(--layout-s); --template: var(--template-s); --gap-width: 1rem; } /* manipula variables por viewport */ @media (min-width: 48rem) { :root { --layout: var(--layout-l); --template: var(--template-l); } } /* realiza o bind no DOM */ body { display: grid; grid-template: var(--template); grid-template-areas: var(--layout); grid-gap: var(--gap-width); justify-content: center; min-height: 100vh; max-width: calc( var(--paragraph-width) + var(--sidebar-width) + var(--gap-width) ); padding: 0 var(--gap-width); }
Todas as global variables são definidas no topo e ordenadas por viewport. Essa seção efetivamente se torna a Definition of Behavior, esclarecendo questões como:
Abaixo estão as definições de regras, ordenadas por componente. As Media Queries não são mais necessárias aqui, porque elas já estão definidas no topo e colocadas em variables. Podemos simplesmente codificar em nossas stylesheets sem interrupções neste ponto.
Um caso especial de pseudo classes é o :target selector, que pode ler o hash fragment da URL. Aqui está uma demonstração que usa essa mecânica para simular uma experiência semelhante a SPA:
Eu escrevi um post sobre isso. Só esteja ciente de que isso tem algumas implicações sérias de acessibilidade e precisa de alguma mecânica JavaScript para realmente ser livre de barreiras. Não faça isso em um live environment.
Manipular CSS variables se tornou uma ferramenta muito poderosa agora. Também podemos aproveitar isso em JavaScript:
// configura --s em :root document.documentElement.style.setProperty('--s', e.target.value); // configura --s scoped para #myID const el = document.querySelector('#myID'); el.style.setProperty('--s', e.target.value); // lê variables de um element const switch = getComputedStyle(el).getPropertyValue('--s');
Os exemplos de codepen acima funcionam exatamente assim.
CSS é muito capaz de definir layout systems inteligentes e reativos. Suas estruturas de controle e algoritmos podem ser um pouco estranhos em comparação com outras linguagens, mas eles estão lá e estão à altura da tarefa. Vamos parar de apenas descrever alguns styles e começar a fazer eles funcionar.
Artigo escrito por Daniel Schulz
以上是用 CSS 寫邏輯的詳細內容。更多資訊請關注PHP中文網其他相關文章!