首頁  >  文章  >  web前端  >  用 CSS 寫邏輯

用 CSS 寫邏輯

PHPz
PHPz原創
2024-08-05 19:44:521016瀏覽

Escrevendo Lógica em CSS

注意:我剛剛翻譯了下面的文字並將其發佈在這裡。參考文獻在本文末。

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 有一篇關於此的深入文章,甚至用偽代碼解釋了他的演算法。

Conditional Styling

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.

Automatic contrast colors

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.

Limpando as stylesheets

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:

  • Quais aspectos globais da stylesheet temos? Estou pensando em coisas como font size, colors, medidas repetidas, etc.
  • Quais aspectos que mudam frequentemente nós temos? Container widths, Grid layouts e similares vêm à mente.
  • Como os valores devem mudar entre as viewports? Quais global styles se aplicam a qual viewport?

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.

Leando o hash parameter

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.

Definindo Variables ​​em JavaScript

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.

Resumo

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.

Fonte

Artigo escrito por Daniel Schulz

以上是用 CSS 寫邏輯的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn