首页  >  文章  >  web前端  >  用 CSS 编写逻辑

用 CSS 编写逻辑

PHPz
PHPz原创
2024-08-05 19:44:521077浏览

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