SELECT 1
Entry 0122026.10.22 목
One launch a day. Picked, run, explained.

2026.10.22 목

Sumi.css: 클래스 없이 HTML 꾸미기

오늘의 픽: Sumi.css

Sumi.css 는 HTML 요소에 클래스를 붙이지 않아도 스타일이 적용되는 CSS 프레임워크다.

오늘의 픽으로 선정한 이유는 사용자의 CSS 로 덮어쓰기 쉽도록 요소 스타일의 명시도를 0으로 설계했기 때문이다.

exit 0실행함작동한다. 클래스 없이 작성한 페이지가 꾸며졌다.
클래스 없이 작성한 페이지. 내비게이션, "Welcome" 과 "Hello, ink." 제목, 이메일 입력란, 선택 상자, Save 와 Cancel 버튼 그룹, 파일 크기 표, Details 접기 요소
README 의 빠른 시작대로 클래스 없이 HTML 을 작성하고 sumi.min.css 만 연결한 페이지. 데스크톱 화면, 너비 1280px.
출처
Show HN
만든 방식
CSS

무엇이 문제인가

관리 화면이나 문서 페이지처럼 간단한 HTML 에도 보기 좋은 기본 스타일이 필요하다. Bootstrap 공식 문서에 따르면, Bootstrap 은 요소 선택자로는 브라우저 기본값만 정리하고, 그 이상의 스타일은 클래스로만 적용한다. 버튼은 .btn 과 색상 클래스를, 표는 .table 을 붙여야 Bootstrap 스타일이 적용된다. 그래서 Bootstrap 스타일이 필요한 요소마다 프레임워크의 클래스가 들어간다. 다른 CSS 프레임워크로 바꾸려면 이 클래스를 전부 바꿔야 한다.

어떻게 해결했나

Vladimir Carrer 는 2026년 10월 21일 Hacker News 에 Show HN개발자 커뮤니티 Hacker News 에서 자신이 만든 프로덕트를 소개하는 글. 제목이 "Show HN:"으로 시작한다. 글로 클래스리스 CSSHTML 요소에 클래스를 붙이지 않아도 요소 이름만으로 스타일을 적용하는 CSS 프레임워크. 프레임워크 Sumi.css 를 공개했다. HTML 문서에 sumi.min.css 를 연결하면 제목, 폼, 표, 버튼, 내비게이션이 클래스 없이 꾸며진다. 그리드 레이아웃이나 글자가 큰 도입 문단처럼 요소만으로 정할 수 없는 모양에만 .grid, .lead 같은 클래스를 지정한다.

요소 스타일은 :where()괄호 안에 쓴 선택자가 고르는 요소를 그대로 선택하되, 명시도는 0으로 계산되는 CSS 선택자. 선택자로 감싸져 있다. 그래서 요소 스타일의 명시도같은 요소에 CSS 규칙 여러 개가 겹칠 때 어느 규칙을 적용할지 정하는 점수. ID 선택자, 클래스와 속성 선택자, 요소 선택자의 개수로 계산한다.가 0이다. README 에 따르면 사용자가 요소 이름만으로 규칙을 작성해도 Sumi 의 값을 덮어쓸 수 있다. 색, 글꼴, 크기, 모서리는 모두 CSS 변수로 정의돼 있다. 다크 모드는 운영체제 설정을 따른다. data-theme 속성으로 라이트나 다크 모드를 고정할 수도 있다.

무엇이 다른가

첫째, 스타일을 적용하는 대상이 다르다. Bootstrap 은 클래스로 스타일을 적용하므로 <button> 도 .btn 이 있어야 버튼 모양이 된다. Sumi 는 요소 자체에 스타일을 적용하므로 마크업에 프레임워크의 클래스가 들어가지 않는다. 다만 같은 요소를 여러 모양으로 꾸미려면 결국 클래스가 필요하다. Sumi 도 그리드에는 클래스를 제공한다.

둘째, 덮어쓰는 방식이 다르다. 명시도 규칙에 따라 Bootstrap 의 .btn 규칙은 button 처럼 요소 이름만 쓴 규칙보다 우선한다. Sumi 의 요소 스타일은 명시도가 0이라 요소 이름만으로 덮어쓸 수 있다. 다만 오늘 내비게이션 링크의 색과 버튼 그룹 안 버튼의 마진, 모서리는 덮어쓰지 못했다. 이 값을 결정한 Sumi 의 규칙은 :not() 이나 속성 선택자가 :where() 밖에 있거나 important 선언이 붙어 있었다.

셋째, 크기와 범위가 다르다. 오늘 두 파일을 gzip -9 로 압축하자 sumi.min.css 는 Bootstrap 5.3.3 의 bootstrap.min.css 의 4분의 1보다 작았다. Bootstrap 에는 유틸리티 클래스와 자바스크립트 컴포넌트가 함께 있다. Sumi 는 자바스크립트를 사용하지 않는다. 접기와 모달은 <details> 와 <dialog> 요소의 동작에 의존한다.

무엇이 편해지나

  • 디자이너 없이 관리 화면이나 문서 페이지를 만드는 개발자. HTML 만 작성하고 CSS 파일을 연결하면 폼과 표가 정돈된 모양으로 표시된다. 오늘 클래스를 하나도 쓰지 않은 페이지에서 폼과 표가 꾸며졌다.
  • 비전공 동료에게 HTML 수정을 맡기는 팀. 클래스 이름을 몰라도 요소만 작성하면 모양이 유지된다. HN 스레드에는 비전공 동료에게 HTML 수정을 맡겼다는 댓글이 있다. 이런 사용 방식은 오늘 확인하지 못했다.

어떻게 만들었나

  • 제작자 Vladimir Carrer 혼자 커밋 10개를 올렸다. 첫 커밋은 10월 20일, 마지막 커밋은 10월 21일이다(작성자 시간대 기준).
  • sumi.css 는 957줄이고 섹션마다 주석이 달려 있다. 공백과 주석을 지운 sumi.min.css 는 28,245 바이트다.
  • :where(), :has(), color-mix() 를 사용하므로 Chrome 과 Edge 는 111, Firefox 는 121, Safari 는 16.2 부터 지원한다.

실행해 보니

저장소를 클론해 Chromium(Playwright)에서 아래 순서로 시험했다.

  1. 크기. sumi.min.css 를 gzip -9 로 압축하자 6,874 바이트(6.7 KiB)였다. Bootstrap 5.3.3 의 bootstrap.min.css 를 같은 방법으로 압축하자 30,777 바이트였다.
  2. 클래스 없이 작성한 페이지. README 의 빠른 시작대로 클래스 없이 HTML 을 작성하고 sumi.min.css 만 연결했다. 내비게이션, 폼, 버튼 그룹, 표, 접기 요소가 모두 잘 꾸며졌다.
  3. 덮어쓰기. 요소 22개를 골라, 선택자에 요소 이름만 쓴 CSS 를 직접 작성했다. 색, 배경색, 왼쪽 마진, 왼쪽 패딩, 왼쪽 위 모서리 반경, 글자 크기 여섯 속성을 바꿨다. 이 CSS 를 Sumi 보다 먼저 연결해도 나중에 연결해도 값 132개 가운데 129개가 적용됐다.
  4. 덮어쓰지 못한 값. 현재 페이지 링크의 색은 nav a 규칙으로 바뀌지 않고 :where(nav) [aria-current]:not([aria-current="false"]) 규칙의 색이 유지됐다. 보통 내비게이션 링크로 다시 시험하자 그 색도 nav a 로 바뀌지 않았다. :where(nav) :where(a):not([role="button"]) 규칙의 :not() 이 :where() 밖에 있어 명시도가 0이 아니다. 버튼 그룹 안 버튼의 왼쪽 마진과 모서리도 button 규칙으로 바뀌지 않고 [role="group"] > * 규칙의 값이 유지됐다. 이 규칙의 마진에는 important 선언이 붙어 있다. 제작자는 README 에서 요소 스타일의 명시도가 0이라 직접 작성한 CSS 가 important 선언 없이 항상 적용된다고 했다.
  5. 다크 모드. Playwright 로 다크 모드 설정을 에뮬레이션하자 배경이 흰색에서 rgb(15, 18, 22)로 바뀌었다. data-theme 을 반대 모드로 지정하자 에뮬레이션한 설정과 관계없이 페이지가 그 모드로 표시됐다.
  6. 접근성. Tab 키로 이동하자 링크에 2px 실선 포커스 링이 표시됐다. 동작 줄이기 설정에서는 버튼의 트랜지션 시간이 0.01ms 로 줄어 눈에 보이는 움직임이 없어졌다.
  7. 모바일. iPhone 13 에뮬레이션에서 문서 페이지에 가로 스크롤이 생기지 않았다.
== user CSS before sumi: 3 of 132 values lost
  #navcur(nav a) color=rgb(47, 91, 234)
  #gbtn2(button) margin-left=-1px
  #gbtn2(button) border-top-left-radius=0px
== user CSS after sumi: 3 of 132 values lost
Sumi 문서 페이지의 다크 모드. 어두운 배경에 Sumi v1.0 제목과 Copy sumi.css 버튼, 6.7 KB gzipped 표시
Playwright 로 다크 모드 설정을 에뮬레이션하고 연 문서 페이지. iPhone 13 에뮬레이션.
Sumi 문서 페이지의 라이트 모드. 제목 Sumi v1.0, 소개 문장, Copy sumi.css 와 Customize tokens 버튼, 오른쪽에 Quick start 코드
같은 문서 페이지의 라이트 모드. 데스크톱 화면, 너비 1280px.

확인하지 못한 것

  • Safari 와 Firefox 에서의 렌더링. README 의 지원 버전에서 같은 페이지를 열어 Chromium 과 같게 보이는지 확인하자.
  • 스크린 리더. VoiceOver 나 NVDA 로 ARIA스크린 리더 같은 보조 기술에 요소의 역할과 상태를 알리는 HTML 속성 규격. aria-current, aria-invalid 같은 속성이 있다. 속성 aria-invalid 와 aria-current 의 상태가 읽히는지 확인하자.

판정

작동한다. 클래스 없이 작성한 페이지가 꾸며졌다. 다만 Bootstrap 처럼 유틸리티 클래스와 자바스크립트 컴포넌트를 제공하지는 않는다. 디자이너 없이 관리 화면이나 문서 페이지를 만들고, 마크업을 클래스 없이 유지하고 싶은 경우에 써 볼 만하다. 유틸리티 클래스로 화면을 세밀하게 조정하는 팀이라면 이 프로덕트는 적합하지 않다.

얻어갈 것

  • 덮어쓰기 쉬운 CSS 를 만든다면 속성 선택자도 :where() 안에 넣자. Sumi 의 [aria-current] 와 [role="group"] 선택자는 :where() 밖에 있었다.
  • 크기를 표기할 때는 압축 전 크기와 압축 수준도 함께 명시하자. sumi.min.css 는 압축하지 않으면 28,245 바이트, gzip -9 로 압축하면 6,874 바이트였다.

시작하기

  1. curl -LO https://cdn.jsdelivr.net/gh/vladocar/Sumi.css/sumi.min.css
  2. <link rel="stylesheet" href="sumi.min.css">
필요한 것
Chrome 과 Edge 는 111, Firefox 는 121, Safari 는 16.2 이상. README 에 따르면 더 오래된 브라우저에서는 호버와 포커스 색이 단순해진다 · 빌드 도구, 자바스크립트, 의존성은 필요 없다
비용
MIT, 무료.

개발 중에는 주석이 달린 sumi.css 를, 배포에는 sumi.min.css 를 연결한다.

실행해서 확인한 절차다.

진행

  1. 3일활발
  2. 7일예정
  3. 15일예정
  4. 30일예정
  5. 90일예정
  6. 180일예정
  7. 365일예정

최근 확인 3일, 2026.10.24 토

런칭 이후 커밋
2 → 3
스타
102 → 169
마지막 커밋
2026.10.23
HN 득표
67 → 99
  • 모달에 마진을 추가했다.

전체 이력 보기 →