数年間、CSS のステート予測可能性向上のために尽力しました。

2026/04/23 21:37

数年間、CSS のステート予測可能性向上のために尽力しました。

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

Tasty は、開発者が複雑な CSS ステートを管理する方法を革新し、宣言的な状態マップを互いに排他的なセレクタにコンパイルすることで、カスケードにおける従来のソース順序依存性に起因する曖昧さや意図しないバグを効果的に排除します。静的モデルから動的セレクタ生成へシフトさせることで、Tasty は疑似クラスやメディアクエリを超えて確定的なロジックを保証し、不安定なレイアウトのトリックに頼らず動作します。このソリューションは、Cube UI Kit 向けにボタンやドロップダウンなどのスケーラブルな設計プリミティブを構築する過程で直面した現実的な課題から生まれました。現在、Enterprise 環境での本番利用において 100 を超えるコンポーネントをサポートしています。ツールは、単なるオブジェクト形式から、高い制約のあるデザインシステムの要件を压力下でも扱うことができる堅牢な原子 CSS ジェネレーターへと成功して移行しました。GitHub Issues を通じたアクティブなコミュニティのフィードバックが将来の開発方向を形作りつつ、Tasty はワンオフのページではなく長期的なコンポーネント改修を必要とするチームにとって持続可能な前進の道筋を提供します。採用者は、インターフェースが複雑化するにつれて、有意に少ないリグレッションとより予測可能で安定した動作を期待できます。

本文

CSS の制約からの解放:Tasty というアプローチ

2 つの CSS ルールの順序を入れ替えるだけで、ロジックを変更せずにコンポーネントを壊した経験はありませんか?

  • .btn:hover { background: dodgerblue; }
  • .btn[disabled] { background: gray; }

これらのセレクターはすべて特定性(0, 1, 1)を持っています。ボタンがホバー状態かつ無効化されている場合、ブラウザはソースコードの順序に従って解決します。

:hover
ルールが後に来る場合、無効化されたボタンが青色になります。逆に
[disabled]
ルールが後にある場合は、そのままグレーのままです。

一見小さな問題に見えますが、これはより大きな課題を示しています。CSS におけるコンポーネントの状態管理は、多くの場合「オーバーラップ」に依存しています。

コンポーネントの状態が一つや二つのみであれば、その重なり具合はまだ管理可能です。しかし

:hover
:active
、無効化状態、ダークモード対応、レスポンシブ幅、データ属性、コンテナクエリ、オーバライドなどを加えればすぐに管理性が失われます。もはや単にスタイルを書いているだけではなくなりますが、頭の中で「解決システム」を維持していることになります。

その問題は、偶発的な競合として現れるだけでなく、実際の要件が積み重なるにつれて、既存のコンポーネントを安全にカスタマイズするのが次第に難しくなっていきます。

私はコンポーネントシステムを構築する際、繰り返し直面した課題でした。サンプルコードや玩具のような例ではありません。実際のボタン、入力フィールド、パネル、ドロップダウンリスト、そして設計システムの基本要素などで経験しました。最も難しいのは、最初バージョンのコンポーネントを書くことではなく、その後で拡張を行う際に「全体の状態解決問題」を再び開かないようにすることです。

ある時点で、「このセレクターを書くにはどうすれば?」と考えるのをやめ、より良い問いを立てるようになりました:

もしコンポーネントの状態を宣言的に表現でき、それを決定論的にするためには.compiler(コンパイラ)がセレクターロジックを処理するならば?

その問いが最終的には Tasty へと発展しました。

1 分間で行うアイデア説明

競合しながらカスケードと特定性で勝敗を決めるセレクターを書くのではなく、プロパティの可能な状態を「マップ」として記述したいと考えました:

import { tasty } from '@tenphi/tasty';

const Button = tasty({
  as: 'button',
  styles: {
    fill: {
      '': '#primary',
      ':hover': '#primary-hover',
      ':active': '#primary-pressed',
      '[disabled]': '#surface',
    },
  },
});

優先順に適用されると、以下の意味を持ちます:

  1. 無効化されている場合は
    #surface
    を使用
  2. それ以外でアクティブ(クリック中)の場合は
    #primary-pressed
    を使用
  3. それ以外でホバーしている場合は
    #primary-hover
    を使用
  4. それ以外の場合は
    #primary
    を使用

重要なのはその後です。Tasty はこの状態マップを、重なり合うことが不可能なセレクターに変換します:

/* [disabled] が確実に優先される */
.t0[disabled]                                { background: var(--surface-color); }

/* :active は無効化されている場合は除外される */
.t0:active:not([disabled])                   { background: var(--primary-pressed-color); }

/* :hover は :active または [disabled] の場合を除外される */
.t0:hover:not(:active):not([disabled])       { background: var(--primary-hover-color); }

/* デフォルトは上記いずれかが合致する場合は除外される */
.t0:not(:hover):not(:active):not([disabled]) { background: var(--primary-color); }

これでカスケードによる競合の余地は一切なくなり、同時にどのブランチが一致してもよいという状態はなくなります。

そして本当に報われるのは後です。このマップを拡張したり変更したりするのは、従来の CSS で同等のセレクターロジックを再検討することよりも遥かに容易になります。

これが全体の本質です:著者が既に優先順位を定義した場合、生成されるセレクターはその優先順位を明確にすべきである

ボタンの例を示唆する以上の理由

ホバー状態かつ無効化されたボタンは問題を見やすくするための最も簡単なケースに過ぎません。本質的な痛みの始まりは、より微妙な状態で状態同士が交差する場合です。

  • ダークモードはルート属性から来るのか、
    prefers-color-scheme
    から来るのか、あるいは両方から来るのか
  • 狭いコンテナ内での間隔変更だが、タブレット幅のみで適用される場合
  • 破損系(destructive)バリエントはホバー時には振る舞いが異なるが、ローディング時は異なる場合
  • 親テーマが子へのオーバライドを切り替えさせる場合

それぞれルール単独では理解可能ですが、問題なのはそれらの間の相互作用界面です。その相互作用界面こそが CSS が脆く感じる起点となります。小さな変更でもどのブランチが重なるかが変わる可能性があります。無害なリファクタリングさえもソースコード順序によるバグへと転換することがあります。既存のコンポーネントを拡張すると、以前は解決済みと思っていたセレクターロジックを再び開かされることもあります。

私は「新しい状態を追加する際に、頭の中で全体のセレクター行列を再導出する必要がない」というモデルを目指しました。

なぜこれほど時間がかかったのか

核心的なアイデア自体はシンプルです。しかしそれを実際のツールに変えるのは難しいでした。「単純な状態条件では動作する」から「現実世界のコンポーネントシステムを支援できるものになる」までには、数年と数百回の反復が必要でした。

困難だったのは、一つのうまいセレクターを生み出すことではなく、これらがすべて同時に出現した際にも整合性を保つシステムを構築することです:

  • :hover
    :active
    などの擬制クラス
  • 属性、ブール修飾子、値に基づく修飾子
  • ルートレベルの状態
  • メディアクエリ
  • コンテナクエリ
  • ネスト型や複合セレクター
  • スタイルの拡張と安全なオーバライド
  • ステyling モデルの上層に並べられた型付けされた API

モデルが広がっていくたびに、当初のアイデアがまだ成立しているか確認する必要がありました。時には成り立つこともあれば、非常に成り立たないこともあります。

DSL を破断させ、内部で状態をどのように表現すべきかを再考し、コンパイラの大きな部分を再構築して同じ約束(著者が優先順位を定義すれば、生成されるセレクターはその優先順位を明確にする)を守る必要がある時期もありました。

困難さは技術的な部分と概念的な部分の両方から来ます:

  • 技術的な側面 は、パース、正規化、セレクター生成、キャッシュ、拡張ルール、そして実用的であるための出力速度の最適化などに関わります。
  • 概念的な側面 がより困難でした。Tasty の本質とは何かを常に決断し続ける必要がありました。「より使いやすき CSS オブジェクト形式なのか」「アトミック CSS ジェネレーターなのか」「設計システムの言語なのか」「状態を持つコンポーネントスタイルのためのコンパイラなのか」など。実践的には、それらすべてが一度に発展していくため、全体が内部的に整合性を持つと感じるまで、境界線を何回も再描く必要がありました。

長らく、このアイデアが十分にスケールし、その労力を正当化できるものになるか確信を持っていませんでした。初期には局所的には機能していました。しかし設計システム全体で信頼できるツールに発展させるまでには長い道のりがありました。

これは抽象的な実験だけではありません。Tasty は Cube UI Kit の初めからそれを支えてきました。現在は 100 以上のコンポーネントを跨ぎ、Cube Cloud という実際のエンタープライズ製品の背後にあるシステムになっています。初期バージョンは内部で完全に実験的でしたが、本番環境でのプレッシャーとチームからのフィードバックを通じて、モデルは自らの形を得ました。

私にとって最も重要な部分

私は「互いに排他的なセレクター」が興味深いのは因为它们がうまいからだと考えません。むしろ、著者が本来負うべきではない種類の曖昧さを排除するためであると信じています。

コンポーネントをスタイル化する際、私は各意味のある状態での外観を記述したいと思っています。常に状態同士が交差するたびに、ブラウザのタイブレーカーロジックを手動でエンコードしたくないのです。Tasty が追い求めているのは以下の成果です:

  • コンポーネントの振る舞いが予測可能になる
  • ソースコード順序による偶発的な後退が減少する
  • 既存コンポーネントの拡張が容易になる
  • デザインシステムが複雑化するほどに価値が増えるスタイルモデルを得られる

もし小さなランディングページをスタイリングしているのであれば、これはおそらく過剰な仕組みと言えます。単純な CSS が適切な答えであることが多いです。しかし数年間の反復やバリエーションの増加、テーマの拡張、複数作者によるコンポーネント構築を行う場合、予測可能性は非常に実践的な方法で複利効果を生み出します。

少し大きな例

いくつか追加の変数を持つ同じアイデア:

const Panel = tasty({
  styles: {
    flow: {
      '': 'column',
      '@media(w >= 768px)': 'row',
    },
    fill: {
      '': '#surface',
      'theme=danger & :hover': '#danger-hover',
      '@root(schema=dark)': '#surface-dark',
    },
    padding: {
      '': '4x',
      '@(sidebar, w < 300px)': '2x',
    },
  },
});

ここで、モデルが通常のセレクター記述よりも有用だと感じるポイントです。三つのプロパティがあり、それぞれ異なる関心事を持ちます——メディアクエリ、コンテナクエリ、修飾子、ルート状態、擬制クラス——著者はそれらがどのように相互作用するかを一度も考える必要がありません。コンパイラがすでに理解しています。

この投稿とは、そして何ではないか

これは Tasty の完全版ガイドではありません。Tasty は他にも型付けされたコンポーネント API、サブ要素、SSR 統合、ランタイムゼロ抽出、エディタツール、リンティング、トークン、レシピなど多数の機能を持っています。それらも全て重要であり、ツールが実用上有用な理由の一部です。しかしこれらは主要なアイデアの下流にあります。

主要なアイデアは依然としてこの通りです:コンポーネントの状態は記述しやすく、曖昧になることが困難であるべき

この一文を「リリースに安心して使えるツール」に変えるまでには数年かかりました。

この内容に共感いただけた場合

ブラウザ上のプレイグラウンドで Tasty を試すことができます。あるいは、完全な言語と機能セットについてはドキュメントを読むことも可能です。

実際に試してくださった場合、率直なフィードバックを心から歓迎します。最も有用なフィードバックは「これはかっこいい」ではなく、より具体的なものが多いです:

  • モデルがどこですぐに理解できたか
  • 不慣れに感じた箇所はどこか
  • 命名が混乱した場所はどこか
  • ドキュメントでスキップされた思考プロセスがあるか
  • 抽象化が実際の問題を解決するか、あるいは失敗しているか

そのようなフィードバックはプロジェクトの始まりから形づくりに影響を与え、今もなお影響を与えています。何か不親切、不自然、不足を感じる場合は、GitHub Issues で共有していただくのが最適です。

ここまで読んでいただきありがとうございました。この投稿には私にとって大きな意味があります。なぜなら、長年取り組んできた問題についてだからです。

リンク: ドキュメント | プレイグラウンド | GitHub | npm

同じ日のほかのニュース

一覧に戻る →

2026/04/24 3:01

文書の見直しのお手伝いをいたしますが、ご提示いただいた「GPT-5.5」という入力は、翻訳や編集の対象となる文章を含んでおりません。 ルールに従って文書の体裁を整える対象となりますよう、該当する原文をご提供ください。 また、「GPT-5.5」という名称は、現時点で公開されている正式版のモデル名とは一致しておりません(現在最新シリーズは GPT-4o や GPT-4 Turbo などです)。 特定のテキストを処理させていただく場合は、その内容をお貼り付けください。

## Japanese Translation: OpenAI は、エージェント型コーディング、高度なコンピューター操作、知識作業、科学研究を特に目的に設計された、至今に至るまで最も知的で直感的なモデルである GPT‑5.5 を発表します。このモデルは GPT‑5.4 と同等のトークンあたり遅延を実現し、Codex タスクにおいて著しくトークン使用量を削減することで、NVIDIA GB200 および GB300 NVL72 システム上で Codex が負荷分散のヒューリスティクスを最適化するのを支援しながら、生成速度を 20% 以上向上させています。複雑なコマンドラインワークフローに関する Terminal-Bench 2.0 で 82.7% の精度、実世界の GitHub アイシュー解決における SWE-Bench Pro で 58.6% の精度を実現し、最先端のパフォーマンスを提供します。Codex においては、実装からリファクタリング、デバッグに至るまでのエンドツーエンドのエンジニアリングタスクに優れ、大規模システム全体を文脈として保持しつつ、曖昧なエラーに対しても推論を行います。安全性は引き続き最優先事項であり、モデルは新たなサイバーおよび生物学リスクに対して厳格に評価され、レッドチームによってテストされ、ほぼ 200 の信頼できるパートナーからのフィードバックに基づいて改良され、「生物学・化学およびサイバーセキュリティ能力において OpenAI の準備度フレームワークの「High」カテゴリー分類」を受領しました。GPT‑5.5 は、ChatGPT および Codex で Plus、Pro、Business、Enterprise ユーザーへ段階的に導入されており(gpt-5.5 Pro は Pro、Business、Enterprise 向けに利用可能)、API アクセスも近日中に gpt-5.5 について入力トークン当たり 5 ドル、出力トークン当たり 30 ドル(gpt-5.5-pro は 30 ドル/180 ドル)、および Very soon at $5/1M input tokens and $30/1M output tokens for gpt-5.5 ($30/$180 for gpt-5.5-pro) のレートで利用可能になります。OpenAI はまた、Trusted Access for Cyber を通じて「cyber-permissive」モデルの提供範囲を拡大し、検証済みユーザーに制限が少なくなった高度なセキュリティツールへのアクセスを提供します。知識作業ベンチマークでは、プロンプトチューニングなしで GDPval で 84.9%、OSWorld-Verified で 78.7%、Tau2-bench Telecom で 98.0% の強力な結果を示しました。 ## Text to translate: ## Summary: OpenAI is launching GPT‑5.5, its smartest and most intuitive model yet, specifically engineered for agentic coding, complex computer use, knowledge work, and scientific research. The model matches GPT‑5.4 per-token latency while significantly reducing token usage for Codex tasks, achieving faster generation speeds by over 20% when serving on NVIDIA GB200 and GB300 NVL72 systems (with help from Codex in optimizing load balancing heuristics). It delivers state-of-the-art performance with 82.7% accuracy on Terminal-Bench 2.0 for complex command-line workflows and 58.6% on SWE-Bench Pro for real-world GitHub issue resolution. In Codex, it excels at end-to-end engineering tasks—from implementation and refactoring to debugging—while holding context across large systems and reasoning through ambiguous failures. Safety remains a top priority: the model was rigorously evaluated against emerging cyber and biology risks, tested by redteamers, and refined with feedback from nearly 200 trusted partners, earning a "High" classification under OpenAI's Preparedness Framework for biological/chemical and cybersecurity capabilities. GPT‑5.5 is rolling out to Plus, Pro, Business, and Enterprise users in ChatGPT and Codex (with GPT‑5.5 Pro available to Pro, Business, and Enterprise), and API access will be available very soon at $5/1M input tokens and $30/1M output tokens for gpt-5.5 ($30/$180 for gpt-5.5-pro). OpenAI also expands "cyber-permissive" models via Trusted Access for Cyber, allowing verified users to access advanced security tools with fewer restrictions. Knowledge work benchmarks show strong results: 84.9% on GDPval, 78.7% on OSWorld-Verified, and 98.0% on Tau2-bench Telecom without prompt tuning.

2026/04/23 23:17

Bitwarden CLI、継続中の Checkmarz サプライチェーン攻撃で乗っ取られたと判明

## 日本語訳: セキュリティ研究者の InstallSocket が、継続中の「Checkmarx」キャンペーンの一環として、Bitwarden CLI ツール(@bitwarden/cli バージョン 2026.4.0)を対象とした重大なサプライチェーン攻撃を発見した。当該侵害は npm パッケージ内の `bw1.js` ファイルにあり、Bitwarden のビルドパイプラインにおける改ざんされた GitHub Action を利用して悪意のあるコードを注入したものである。これは CLI を使用する組織に対して直ちに脅威をもたらすものの、Chrome 拡張機能や MCP サーバーなどの他の配信形態は影響を受けていない。 悪意のあるペイロードは、主要なクラウドプロバイダー(AWS、Azure、GCP)、npm、SSH および Claude/MCP の設定ファイルにアクセスするためにメモリーをスクレイピングし、機密認証情報を収集することを目的としている。データを流出させる手法としては、「Dune 風」の命名規則を用いた GitHub API アップロードや、npm トークンを盗むためのパッケージのリパブリッシュが含まれる。このリスクに直面している組織は、InstallSocket からのさらなる技術分析的な確認を待たずに、直ちにビルドログを検証して侵害の指標(改ざんされたシェルプロフィール(`~/.bashrc`、`~/.zshrc`)、特定のエビディングファイル(`/tmp/tmp.987654321.lock`)、「Shai-Hulud」や"Butlerian Jihad"といったキーワードなど)を特定し、すべての公開された機密情報(SSH キー、トークン、CI/CD クレデンシャル等)を再発行するよう求める。

2026/04/24 5:14

「『インターネットを 1999 年あたりのまま使いこなすような』感覚を持つ」あるいは「ネットの使い方を、まるで 1999 年のあの頃のように(古き良き時代のように)捉えている」という意味で解釈できます。

## Japanese Translation: 著者は、現代のインターネット利用習慣が私達をアルゴリズムによる操作と「ドゥームスクロリング(絶え間ないスクロール)」という循環に陥れ、ウェブの可能性の僅かな部分にのみ留まらせていることを主張している。注意の代理権を取り戻すためには、社会メディアプラットフォームから、RSS フィードや IRC/XMPP プロトコル、HTTP/SMTP サービスといった、企業インセンティブではなく制約によって設計された直接データソースへ移行する必要がある。このアプローチは、深い高品質なコンテンツへのアクセスを保証すると同時に、反復的な LLM ポストのような低努力な AI 生成コンテンツ(スロープ)を能動的に拒否することを可能にする;著者は、「これはこれではなく、あれだ」といった類の明らかなフレーズが付けられたコンテンツを特に避けている。 歴史的には、1999 年の時点で人口のおよそ 4% がインターネットを利用していただけであり、その時点ではソーシャルメディアとアルゴリズムが現在の約 75% の浸透率を支配する以前のことだった。提案される道筋は、Miniflux などのツールを設定して意図的な購読を通じて独自の現実を編集することを受け入れ、信頼性の高いテキスト通信のために単純なプロトコルを採用すること(1980 年代後半以降の IRC;OMEMO 暗号化を実装したセルフホスト XMPP)、そしてMATRIX/Element といったより有益でないプラットフォームをあえて避ける代わりに確立された標準を採用することを含む。最後に、ユーザーは専門的な検索習慣を採用すべきであり、受動的な閲覧ではなく正確なクエリの作成を通じて意味のある情報を抽出し、技術大手をユーザー主導の注意経済に適応させる可能性がある方向へと推すものである。