본문 바로가기
css

CSS에서 논리 쓰기

by code-box 2022. 2. 22.
반응형

CSS는 스타일 시스템에 초점을 맞춘 고도로 전문화된 프로그래밍 언어이다. 이러한 독특한 사용 사례와 선언적 성격 때문에 때때로 이해하기 어렵습니다. 어떤 사람들은 심지어 그것이 프로그래밍 언어라는 것을 부인하기도 한다. 스마트하고 유연한 스타일의 시스템을 프로그래밍하여 그들이 틀렸다는 것을 증명해 봅시다.

제어 구조

좀 더 전통적인 범용 언어(JavaScript 같은)는 조건(if/then), 루프(loops, for, while), 논리 게이트)와 같은 도구를 제공합니다.

변수

 

변수는 가장 간단한 변수입니다. CSS에서는 Custom Properties라고 합니다(모두가 변수라고 부르지만 심지어 자신의 구문이라고 부르기도 함).

: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, 최대 1분의 1 크기로 캡을 씌우기만 하면 된다. 설명하는 것보다 보는 것이 더 쉬울 것입니다.

그리고 마지막으로, 루프 셀렉터가 있습니다. 그들은 주장을 받아들이는데, 이것은 매우 정확하게 선택하는 공식이 될 수 있다.

section:nth-child(2n) {
      /* selects every even element */
}

section:nth-child(4n + 2) {
      /* selects every fourth, starting from the 2nd */
}

매우 특별한 모서리 케이스의 경우 :nth-child()와 :not()를 다음과 같이 결합할 수 있습니다.

 
section:nth-child(3n):not(:nth-child(6)) {
      /* selects every 3rd element, but not the 6th */
}

:n번째 자식()을 :n번째 유형() 및 :n번째 마지막 유형()으로 바꾸면 이러한 마지막 몇 가지 예제의 범위를 변경할 수 있습니다.

논리 게이트

Ana Tudor는 CSS Logic Gates에 대한 기사를 썼다. 그것들은 변수와 계산을 결합하는 아이디어에 작용한다. 그리고 나서 그녀는 그것으로 3D 모델링과 물체 애니메이션을 계속합니다. 불가사의한 마술처럼 읽히고, 기사가 갈수록 더 미쳐가고, 일반적으로 CSS가 프로그래밍 언어인 이유를 설명하는 가장 좋은 방법 중 하나입니다.

기술

 

올빼미 선택기

* + * {
      margin-top: 1rem;
}

부엉이 선택기는 항목 뒤에 오는 모든 항목을 선택합니다. 여기에 마진톱을 적용하면 그리드 갭처럼 항목 간 간격이 효과적으로 추가되지만 그리드 시스템이 없습니다. 이것은 또한 더 커스터마이징이 가능하다는 것을 의미합니다. 여백 상단을 덮어쓰고 모든 종류의 컨텐츠에 맞게 조정할 수 있습니다. 각 항목 사이에 1렘 간격을 두고 헤드라인 앞에 3렘 간격을 두고 싶으십니까? 올빼미 셀렉터로 그리드에서보다 더 쉽게 할 수 있습니다.

Kevin Pennekamp는 의사 코드로 알고리즘을 설명하는 심층적인 기사를 가지고 있습니다.

조건부 스타일링

 

우리는 변수와 계산으로 특정 규칙을 켜고 끄는 토글을 css 코드에 만들 수 있다. 이것은 우리에게 매우 다용도적인 조건을 제공합니다.

.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%));
}

--s, .box의 값에 따라 경보 스타일을 사용하거나 사용하지 않습니다.

자동 대비 색상

같은 논리로 한 단계 더 나아가 배경색 대비에 따라 달라지는 색상 변수를 만들어 보겠습니다.

 
: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%)
                    );
}

이 조각은 배경의 밝기 값을 반전시켜 HSL 값에서 배경색과 흑백 글꼴 색상을 계산합니다. 이것만으로도 낮은 색상 대비(60% 회색 배경에 40% 회색 글꼴은 거의 읽기 불가능함)가 발생할 수 있으므로 임계값(흰색에서 검은색으로 색이 전환되는 지점)을 빼서 1000과 같이 엄청나게 높은 값을 곱한 후 10%에서 95% 사이로 클램핑하여 유효한 밝기 백분율을 얻겠습니다. 이 모든 것은 스니펫의 시작 부분에 있는 네 가지 변수를 편집하여 제어할 수 있습니다.

이 방법은 HSL 값만을 기반으로 복잡한 색 논리와 자동 테마를 작성하는 데도 사용할 수 있다.

스타일시트 정리

지금까지 가지고 있던 것을 합쳐서 스타일시트를 정리합시다. 뷰포트로 모든 것을 정렬하는 것은 약간 스파게티처럼 보이지만, 구성 요소별로 정렬하는 것은 전혀 기분이 나아지지 않습니다. 변수를 사용하면 두 가지 장점을 모두 누릴 수 있습니다.

 
/* define variales */
: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;
}

/* manipulate variables by viewport */
@media (min-width: 48rem) {
      :root {
                --layout: var(--layout-l);
                --template: var(--template-l);
      }
}

/* bind to 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);
}

모든 전역 변수는 맨 위에 정의되고 뷰포트별로 정렬됩니다. 이 섹션은 효과적으로 행동의 정의가 되어 다음과 같은 질문을 해결합니다.

  • 스타일시트의 어떤 글로벌한 측면을 가지고 있습니까? 글꼴 크기, 색상, 반복측정 등을 생각하고 있습니다.
  • 우리가 자주 변화하고 있는 측면은 무엇인가? 컨테이너 폭, 그리드 레이아웃 등이 떠오른다.
  • 뷰포트 간에 값이 어떻게 변경되어야 합니까? 어떤 전역 스타일이 어떤 뷰포트에 적용됩니까?

다음은 구성 요소별로 정렬된 규칙 정의입니다. 미디어 쿼리는 이미 맨 위에 정의되어 있고 변수에 포함되기 때문에 더 이상 필요하지 않습니다. 이 시점에서 중단 없이 아웃 스타일시트를 코드화할 수 있습니다.

해시 매개 변수 읽기

 

의사 클래스의 특수한 경우 URL의 해시 조각을 읽을 수 있는 :target 선택기가 있습니다. 다음은 이 정비공을 사용하여 SPA와 같은 경험을 시뮬레이션하는 데모입니다.

그것에 대해 글을 썼어요. 이것은 접근성에 심각한 영향을 미치며 실제로 장벽이 없는 자바스크립트 메커니즘이 필요하다는 것만 알아두세요. 실제 환경에서 이러지 마세요.

JavaScript에서 변수 설정

현재 CSS 변수 조작은 매우 강력한 도구가 되었습니다. 또한 JavaScript에서는 이를 활용할 수 있습니다.

    // set --s on :root
    document.documentElement.style.setProperty('--s', e.target.value);

    // set --s scoped to #myID
    const el = document.querySelector('#myID');
    el.style.setProperty('--s', e.target.value);

    // read variables from an alement
    const switch = getComputedStyle(el).getPropertyValue('--s');
        ```

        <div class="content-ad"></div>

        위의 코드펜 예들은 바로 그렇게 작동합니다.

        # 마무리하기

        CSS는 스마트 레이아웃 시스템과 반응형 레이아웃 시스템을 구분할 수 있다. 제어 구조와 알고리즘은 다른 언어들에 비해 조금 이상할 수 있지만, 그들은 거기에 있고 그들은 그 일에 달려 있습니다. 몇 가지 스타일에 대한 설명은 그만하고 작업하도록 합시다.

댓글