# Sumi.css: 클래스 없이 HTML 꾸미기
# Sumi.css: styling HTML without classes

- Site: https://select1.dev/2026-10-22 (English), https://select1.dev/ko/2026-10-22 (Korean)
- Entry: 012
- Published: 2026-10-22 (KST). Launch date: 2026-10-21
- Pick: Sumi.css <https://github.com/vladocar/Sumi.css> (source: Show HN)
- Verified: ran
- What: Sumi.css 는 HTML 요소에 클래스를 붙이지 않아도 스타일이 적용되는 CSS 프레임워크다.
- What (en): Sumi.css is a CSS framework that styles HTML elements without classes.
- Why: 오늘의 픽으로 선정한 이유는 사용자의 CSS 로 덮어쓰기 쉽도록 요소 스타일의 명시도를 0으로 설계했기 때문이다.
- Why (en): It is today’s pick because it gives element styles zero specificity, so the user’s own CSS can override them easily.
- Verdict: 작동한다. 클래스 없이 작성한 페이지가 꾸며졌다.
- Verdict (en): It works. A page written without classes came out styled.
- Tags: css, classless, framework, accessibility, dark-mode

## Checked against the README

- [pass] sumi.min.css 는 gzip 으로 압축하면 6.7 KB 다 — gzip -9 로 6,874 바이트(6.71 KiB. README 의 6.7 KB 는 KiB 기준), gzip 기본값으로 6,898 바이트
- [fail] 요소 스타일은 명시도가 0이라 직접 작성한 CSS 가 !important 없이 항상 적용된다 — 요소 22개에, 선택자에 요소 이름만 쓴 CSS 를 직접 작성해 6개 속성을 바꿨다. Sumi 보다 먼저 연결해도 나중에 연결해도 132개 값 가운데 129개만 적용. nav a 의 color 는 :where(nav) [aria-current]:not([aria-current="false"]) 의 값이, role="group" 안 button 의 margin-left 와 border-top-left-radius 는 [role="group"] > * 의 값(margin 에 !important)이 유지됐다. 보통 nav 링크로 다시 시험하자 color 는 :where(nav) :where(a):not([role="button"]) 의 값이 유지됐다
- [pass] 다크 모드는 운영체제 설정을 따르고 data-theme 으로 고정할 수 있다 — Playwright colorScheme light 와 dark 에서 body 배경이 rgb(255, 255, 255) 와 rgb(15, 18, 22). data-theme 을 반대로 지정하면 그 값을 따랐다

## Measured

- sumi.min.css 압축 크기: 6,874 바이트 (gzip -9 -c sumi.min.css | wc -c. 같은 방법으로 Bootstrap 5.3.3 의 bootstrap.min.css 는 30,777 바이트)

## Progress (days after launch; full history https://select1.dev/2026-10-22/progress)

- day 3 (checked 2026-10-24) [active] commits since launch 3, stars 169, releases 0, contributors 1, last commit 2026-10-23
  - The modal dialog now has a margin.

## 한국어

## 무엇이 문제인가

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

## 어떻게 해결했나

Vladimir Carrer 는 2026년 10월 21일 Hacker News 에 Show HN 글로 클래스리스 CSS 프레임워크 Sumi.css 를 공개했다. HTML 문서에 `sumi.min.css` 를 연결하면 제목, 폼, 표, 버튼, 내비게이션이 클래스 없이 꾸며진다. 그리드 레이아웃이나 글자가 큰 도입 문단처럼 요소만으로 정할 수 없는 모양에만 `.grid`, `.lead` 같은 클래스를 지정한다.

요소 스타일은 :where() 선택자로 감싸져 있다. 그래서 요소 스타일의 명시도가 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
```

## 확인하지 못한 것

- Safari 와 Firefox 에서의 렌더링. README 의 지원 버전에서 같은 페이지를 열어 Chromium 과 같게 보이는지 확인하자.
- 스크린 리더. VoiceOver 나 NVDA 로 ARIA 속성 `aria-invalid` 와 `aria-current` 의 상태가 읽히는지 확인하자.

## 판정

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

## 얻어갈 것

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

### 용어

- Show HN: 개발자 커뮤니티 Hacker News 에서 자신이 만든 프로덕트를 소개하는 글. 제목이 "Show HN:"으로 시작한다.
- 클래스리스 CSS: HTML 요소에 클래스를 붙이지 않아도 요소 이름만으로 스타일을 적용하는 CSS 프레임워크.
- :where(): 괄호 안에 쓴 선택자가 고르는 요소를 그대로 선택하되, 명시도는 0으로 계산되는 CSS 선택자.
- 명시도: 같은 요소에 CSS 규칙 여러 개가 겹칠 때 어느 규칙을 적용할지 정하는 점수. ID 선택자, 클래스와 속성 선택자, 요소 선택자의 개수로 계산한다.
- ARIA: 스크린 리더 같은 보조 기술에 요소의 역할과 상태를 알리는 HTML 속성 규격. aria-current, aria-invalid 같은 속성이 있다.

## English

## The problem

Even a simple HTML page, such as an admin screen or a docs page, needs decent default styles. Bootstrap’s official docs say that Bootstrap only resets browser defaults with element selectors. Any further styling comes only from classes. A button needs `.btn` and a color class to look like Bootstrap, and a table needs `.table`. So every element that needs Bootstrap’s styles carries framework classes, and moving to another CSS framework means changing all of them.

## How it solves it

Sumi.css is a classless CSS framework by Vladimir Carrer. It appeared as a Show HN on Hacker News on October 21, 2026. Sumi styles headings, forms, tables, buttons and navigation without classes when the page links `sumi.min.css`. Classes such as `.grid` and `.lead` are only for things an element alone cannot express, like a grid layout or an intro paragraph in larger type.

Sumi wraps its element styles in :where(), so they have zero specificity. The README says a rule written with just an element name can override Sumi’s values. Every color, font, size and radius is set with a CSS variable. Dark mode follows the system setting, and the `data-theme` attribute can force light or dark mode.

## What is different

The first difference is what gets styled. Bootstrap styles by class, so a `<button>` needs `.btn` to get Bootstrap’s button styles. Sumi styles the element itself, so the markup carries no framework classes. But styling the same element in several ways still needs classes. Sumi also provides classes for grids.

The second difference is how overrides work. Bootstrap’s `.btn` rules have higher specificity than a rule with just an element name such as `button`. Sumi’s element styles have zero specificity, so an element name is enough to override them. But today I could not override three values with element names. They were the color of navigation links, and the left margin and top-left corner radius of a button in a button group. The Sumi rules behind those values had a `:not()` or an attribute selector outside `:where()`, or an important declaration.

The third difference is size and scope. With gzip -9, `sumi.min.css` was less than a quarter the size of Bootstrap 5.3.3’s `bootstrap.min.css`. Bootstrap also ships utility classes and JavaScript components. Sumi uses no JavaScript. It relies on HTML elements such as `<details>` and `<dialog>` for collapsible sections and modals.

## What it makes easier

- Developers who build admin screens or docs pages without a designer. They write HTML and link one CSS file. The forms and tables look tidy. Today a page with no classes at all got styled forms and tables.
- Teams that let non-technical colleagues edit HTML. The styles still apply when they write plain HTML elements without class names. A comment on the HN thread describes this use. I did not test this today.

## How it was built

- The maker, Vladimir Carrer, pushed all 10 commits. The first is dated 2026-10-20 and the last 2026-10-21, in the author’s time zone.
- `sumi.css` is 957 lines with a comment for each section. `sumi.min.css`, with whitespace and comments removed, is 28,245 bytes.
- Because it uses `:where()`, `:has()` and `color-mix()`, it works from Chrome and Edge 111, Firefox 121 and Safari 16.2.

## Running it

I cloned the repository and tested it in Chromium (Playwright) in this order.

1. Size. `sumi.min.css` came to 6,874 bytes (6.7 KiB) with gzip -9. Bootstrap 5.3.3’s `bootstrap.min.css` came to 30,777 bytes the same way.
2. A page without classes. Following the README quick start, I wrote HTML with no classes and linked only `sumi.min.css`. Sumi styled the navigation, the forms, a button group, a table and a collapsible section.
3. Overrides. I picked 22 elements and wrote my own CSS with element-name selectors only. It changed six properties: color, background color, left margin, left padding, top-left corner radius and font size. I linked that CSS before Sumi and after it. In both cases, 129 of the 132 values (22 elements times 6 properties) applied.
4. Values I could not override. The `nav a` rule did not change the color of the current-page link. It kept the color from `:where(nav) [aria-current]:not([aria-current="false"])`. When I tried a plain navigation link, its color did not change either. The `:not()` in `:where(nav) :where(a):not([role="button"])` sits outside `:where()`, so that rule does not have zero specificity. The `button` rule did not change the left margin or top-left corner radius of a button inside the button group either. They kept the values from `[role="group"] > *`. That rule has an important declaration on its margin. The README says element styles have zero specificity, so your own CSS always wins without an important declaration.
5. Dark mode. When I emulated dark mode in Playwright, the background changed from white to rgb(15, 18, 22). When `data-theme` set the other mode, the page showed that mode regardless of the emulated setting.
6. Accessibility. When I tabbed through the page, links showed a 2px solid focus ring. With reduced motion on, the button’s transition duration dropped to 0.01ms, so no motion was visible.
7. Mobile. In iPhone 13 emulation, the docs page had no horizontal scrolling.

```
== 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
```

## Not checked

- How it looks in Safari and Firefox. Open the same page in the versions the README supports.
- Screen readers. Check that VoiceOver or NVDA reads out the ARIA states `aria-invalid` and `aria-current`.

## Verdict

It works. A page written without classes came out styled. But unlike Bootstrap, it offers no utility classes and no JavaScript components. It is worth trying if you build admin screens or docs pages without a designer and want markup free of classes. If your team styles pages with utility classes, Sumi is not the right choice.

## What to take away

- If you write CSS meant to be easy to override, put attribute selectors inside `:where()` as well. Sumi’s `[aria-current]` and `[role="group"]` selectors sat outside `:where()`.
- When you state a size, state the uncompressed size and the compression level too. `sumi.min.css` was 28,245 bytes uncompressed and 6,874 bytes with gzip -9.

### Terms

- classless CSS: A CSS framework that styles HTML by element name alone, without classes on the elements.
- Show HN: A post on Hacker News, a developer community, in which someone presents what they made. Its title starts with "Show HN:".
- :where(): A CSS selector that matches the same elements as the selectors inside it. Its specificity is zero.
- specificity: The score that decides which CSS rule applies when several rules match the same element. It is computed from the number of ID selectors, class and attribute selectors, and element selectors.
- ARIA: A standard set of HTML attributes that tells assistive technology such as screen readers the role and state of an element. Examples are aria-current and aria-invalid.

## Launches the same day

- Sumi.css <https://github.com/vladocar/Sumi.css> (Show HN, 65): 클래스리스 CSS 프레임워크. HTML 요소만으로 스타일이 적용되고 gzip 으로 압축하면 6.7 KB 라고 소개한다.
- Opposable <https://getopposable.com/blog/computer-use-on-the-phone> (Show HN, 11): 안드로이드 조작 앱. 휴대폰 안의 2B 모델이 다른 앱을 조작한다고 소개한다.
- Linkit <https://github.com/blue-idea/linkit> (Show HN, 11): AI 북마크 관리자. 무료 오픈소스라고 소개한다.
- Inca <https://incacad.com/> (Show HN, 6): 3D 앱. Maya 2020 처럼 작동하는 무료 오픈소스 3D 프로그램이라고 소개한다.
- MCP Census <https://mcpcensus.com/> (Show HN, 5): MCP 서버 변경 피드. MCP 서버 48,797개의 변경을 실시간으로 보여 준다고 소개한다.
- guizang-tv <https://github.com/op7418/guizang-tv> (GitHub, 135): 안드로이드 TV 런처. 샤오미 TV 용 간결한 홈 화면이다.
- ian-xhs-carousel <https://github.com/helloianneo/ian-xhs-carousel> (GitHub, 125): 샤오홍슈 카드 생성 스킬. 글이나 메모를 3:4 이미지 카드로 배치하는 Claude Code 스킬이다.
- simple-checker-v1 <https://github.com/Monopoly0024/simple-checker-v1> (GitHub, 93): 코드 검토 스킬. 코드의 기능 단위를 흐름도와 실행 기록으로 확인하는 Codex 스킬이다.
- UseIt Studio <https://www.producthunt.com/products/useit-studio-from-idea-to-delivery> (Product Hunt, 263): AI 디자인 에이전트. 편집할 수 있는 실제 프로젝트 파일을 만든다고 소개한다.
- BAND for Developers <https://www.producthunt.com/products/band> (Product Hunt, 227): 코딩 에이전트 협업 도구. 코딩 에이전트가 팀으로 함께 일하게 한다고 소개한다.
- Needle <https://www.producthunt.com/products/needle-3> (Product Hunt, 220): 아웃바운드 영업 도구. 에이전트를 중심으로 설계한 아웃바운드 영업 엔진이라고 소개한다.
- CertifiQuiz <https://disquiet.io/products/certifiquiz> (Disquiet): 자격증 퀴즈 서비스. 기출 문제를 실시간 대전으로 풀고 틀린 문제를 다시 공부한다.

## Getting started

- Steps: curl -LO https://cdn.jsdelivr.net/gh/vladocar/Sumi.css/sumi.min.css ; <link rel="stylesheet" href="sumi.min.css">
- Needs: Chrome 과 Edge 는 111, Firefox 는 121, Safari 는 16.2 이상. README 에 따르면 더 오래된 브라우저에서는 호버와 포커스 색이 단순해진다, 빌드 도구, 자바스크립트, 의존성은 필요 없다
- Cost: MIT, 무료.
- Note: 개발 중에는 주석이 달린 sumi.css 를, 배포에는 sumi.min.css 를 연결한다.
