コンテンツにスキップ

.krs.style 構文リファレンス

English · 日本語(このファイル)

セレクタ対象
種別service指定した種別の全ノード
複数種別service, domainいずれかの種別の全ノード
タグ[external]指定タグを持つ全ノード
アノテーション@deprecated指定アノテーションを持つ全ノード
複合(種別+タグ)service[external]種別とタグの両方に一致
複合(タグ+アノテーション)[external]@deprecatedタグとアノテーションの両方に一致
複合(種別+タグ+アノテーション)service[external]@deprecatedすべてに一致
ID#ECommerce特定ノードのみ
エッジedge全エッジ
エッジ+タグedge[async]指定タグのエッジ
エッジ 始点edge[from=ApiGateway]指定ノードを始点とする全エッジ
エッジ 終点edge[to=ApiGateway]指定ノードを終点とする全エッジ
エッジ IDedge#criticalWriteedge#A->Bedge#A-->B特定のエッジのみ

セレクタスコア
種別service1
タグ[external]10
アノテーション@deprecated10
種別 + タグservice[external]11
タグ + アノテーション[external]@deprecated20
種別 + タグ + アノテーションservice[external]@deprecated21
ID#ECommerce100
エッジedge1
エッジ + タグedge[async]11
エッジ 始点 / 終点edge[from=ApiGateway]11
エッジ IDedge#criticalWrite101

edge#criticalWrite は 101(ID 100 + edge 種別 1)。 同スコアなら後に書いた方が優先(CSS同様)。


始点 / 終点エッジセレクタ(edge[from=<id>] / edge[to=<id>]

Section titled “始点 / 終点エッジセレクタ(edge[from=<id>] / edge[to=<id>])”

あるノードを始点(または終点)とする全エッジを 1 ルールでまとめてスタイル できる。密な図で残った交差や束を見分ける「color-by-source」の最有力手段で、 これが無いとハブの fan-out を edge#Hub->Target ルールの列挙でしか書けない。

  • edge[from=<id>]始点がノード <id> の全エッジ
  • edge[to=<id>]終点がノード <id> の全エッジ
edge[from=ApiGateway] { color: #3B82F6; } /* ApiGateway の fan-out をまとめて 1 色に */
edge[from=Scheduler] { color: #10B981; }
edge[to=AuthService] { color: #F59E0B; } /* AuthService を呼ぶ全エッジ */

<id> はノード id。usecase→resource 合成エッジ向けに dot-notation の端点 (例: edge[to=OrderDB.OrderTable])も使える。base 形式 edge#PlaceOrder->OrderDB.OrderTable と同じ規則で、id はアクティブビュー上の エッジの from / to 端点と比較される。

どちらも詳細度は 11edge 種別 1 + 端点述語 10)で edge[<tag>] と同格。 タグと併用でき、1 本のエッジが from=to= の両ルールに同時に一致しうる:

edge[from=ApiGateway][async] { stroke-style: dashed; } /* ApiGateway 発の async エッジ */

from / to 以外の属性(例: edge[source=X])は unknown-edge-selector-attribute エラーになる。

Related TPLs: TPL-20260624-04 (端点セレクタはビューが格納する id 形と同じ形で比較すること)。

特定のエッジ 1 本だけにスタイルを適用する。<id> はエッジの canonical id で、 パース後に以下の規則で確定する:

  1. .krs でエッジ宣言(または usecaseresource 行)に #<id> が 書かれていれば、その author id がそのまま canonical id になる
  2. それ以外は base 形式 <from><arrow><to>-> は sync、--> は async
/* `.krs` 側で A -> B "primary" #criticalWrite と書かれた場合 */
edge#criticalWrite { color: #EF4444; }
/* author id が無い場合の base 形式 */
edge#A->B { color: #00FF00; }
/* async の base 形式 */
edge#A-->B { stroke-width: 2px; }
/* dot-notation を含む base id(usecase→resource 合成エッジなど) */
edge#PlaceOrder->OrderDB.OrderTable { direction: down; }

同じ base id を持つエッジが 2 本以上あって両方に author id が無い場合、 パーサが ambiguous-edge-base warning を出し、edge#<base> セレクタは どちらにも一致しない。区別したい場合は .krs 側でいずれかに #<id> を 付ける。詳細は docs/spec/syntax.mddocs/design/edge-id-selector.md を参照。

タグセレクタを優先すべきケース

Section titled “タグセレクタを優先すべきケース”

「read / write の見た目を変えたい」のような 論理分類による上書きedge#<id> ではなく edge[write] / edge[read] を使うこと。タグセレクタは 論理分類に追従するので、usecaseoperations を変更しただけで対象エッジが 正しく追従する。edge#<id> は「この特定のエッジ」を直接指したい場合に 限定して使う。


/* ノード用プロパティ */
background-color: #1D4ED8;
color: #DBEAFE; /* テキスト色 */
border-color: #1E40AF;
border-width: 2px;
border-style: solid; /* solid | dashed | dotted */
border-radius: 8px;
font-size: 13px;
font-weight: bold; /* normal | bold */
font-family: "Noto Sans JP", sans-serif;
opacity: 0.6;
/* エッジ用プロパティ */
color: #94A3B8;
stroke-width: 1.5px;
font-size: 11px;
stroke-style: solid; /* solid | dashed | dotted(正準名、後述) */
border-style: solid; /* solid | dashed | dotted(stroke-style のエイリアス) */
direction: auto; /* up | down | left | right | auto(ヒント、後述) */
label-position: middle; /* start | middle | end | <0.0..1.0> */
label-offset: 0 0; /* <dy>px or <dx>px <dy>px(screen-axis) */
/* karasu固有プロパティ(CSS非対応のため例外) */
shape: box; /* box | user | cylinder | queue | hexagon | cloud | url("...") */
/* アノテーション用プロパティ(バッジ表示) */
badge-color: #EF4444;
badge-icon: "⚠";
badge-label: "非推奨";

stroke-style プロパティ(エッジ)

Section titled “stroke-style プロパティ(エッジ)”

stroke-style はエッジの線スタイル(solid | dashed | dotted)の 正準名である。エッジが既に使っている SVG 系の stroke-* 語彙 (stroke-width)と揃えている。border-style は後方互換のための エイリアスとしてエッジでも引き続き使える — 既存のスタイルシートは そのまま動作する。

edge[async] { stroke-style: dashed; } /* 推奨 */
edge[legacy] { border-style: dashed; } /* エイリアス、同じ効果 */

カスケード後に同一エッジへ両方が宣言されている場合は、宣言順に かかわらず stroke-style が勝つ:

edge { border-style: dotted; stroke-style: dashed; } /* → dashed */

ノードの線スタイルは border-style のみ — stroke-style はノード シェイプには効果を持たない。

Related TPLs: TPL-20260511-02 — 本ドキュメントの css フェンスに宣言されたプロパティはアプリ内 reference データに存在しなければならず、PROPERTY_SCHEMAS の全エントリは 本ドキュメントに記載されていなければならない(stroke-style は正式化前は スキーマのみのゴーストだった — ADR-20260610-01 / #1492 参照)。


キーワード形状主な用途
box角丸長方形service, domain(デフォルト)
user人型(頭+体)user
cylinder円柱db系
queue横向き円柱queue系
hexagon六角形マイクロサービス
cloud雲形外部クラウド

カスタム形状(SVGファイル参照):

service[external] {
shape: url("shapes/cloud.svg");
}

レイアウトヒント(escape hatch)

Section titled “レイアウトヒント(escape hatch)”

最後の手段として使う。 karasu の auto-layout(kind と到達性で決まる 行配置、直交エッジルーティング、ポート分散)はほとんどの図を入力なしで 描けます。レイアウトヒントは、それでも作者の意図を表現できない場合(例: 管理用 actor を右側に固定したい、外部サービスを片側に寄せたい)にだけ 使うこと。まずヒューリスティクスでの吸収を検討し、ヒントは最後に。

同じ layer 内のノードを 3 つのバケット(left / center-もしくは未指定 / right) に振り分けます。center と未指定は同じ中央バケットに入るため、両端だけを 明示的に指定して残りは未指定で済ませられます:

service[external] { column: right; }
queue, database, storage { column: center; }
/* internal service は未指定 → 中央バケットに入る */

各バケット内は既存の並び(system view では宣言順、それ以外では barycenter) を保持します。layer(行)自体を動かす効果はありません。行を変えたく なった場合はヒントを増やす前に auto-layout のヒューリスティクス改善 Issue を立ててください。

外部サービス(system view): column で配置サイドを選ぶ

Section titled “外部サービス(system view): column で配置サイドを選ぶ”

system view では [external] サービスを既定で左右のサイド列に配置します (最下段の行ではありません)。これにより service → external のエッジが水平に 走り、下向きの infra ファンアウトの間を縫わずに済みます。サイドは consume する サービスの位置から自動で決まります(各 external は、それを呼ぶサービスの側へ グルーピングされます)。external サービスに column: left / column: right を 指定すると、その自動割り当てを上書きして指定した側に固定します:

#LegacyBilling { column: left; } /* この外部 SaaS を左側に固定する */

external サービスの column: center / 未指定は、サイドを自動割り当てに委ねます。 (infra kind — database / queue / storage — は [external] タグの有無に 関わらず最下段の行に残ります。Tags を参照。)

Related TPLs: TPL-20260624-04

View挙動
system上記の通り適用。
deploy無視。解決時に style-column-ignored-non-system-view 警告が出る。
org同上。

left / center / right 以外の値は style-column-invalid-value 警告とともに破棄されます。

コンテナの直接の子を畳むグリッドの列数を指定します。既定でもレイアウトは多数の 兄弟をバランス grid に畳み、横長の一行に潰れてズームアウトを強いる状態を避けます (一目で把握できる解像度を保つ。コンセプトの scoped glance / 解像度の軸を参照)。 既定の列数は ≈ 正方形に自動バランスします: 少数(5 個まで)は 1 行のまま、より多い 場合は ceil(sqrt(n)) 列(最大 5 列)で横ではなく縦に伸ばします。

grid-columns はこの既定を特定のコンテナで上書きします。子を再配置したいノード (services なら system、domains なら service、usecases なら domain、member grid なら team)に指定します:

#PlatformSystem { grid-columns: 3; } /* services を 3 列で折り返す */
#BillingDomain { grid-columns: 2; } /* usecases を 2 列で折り返す */

1 行が最大レイヤー幅を超える場合は早めに折り返すため、過大な grid-columns でも フレームを溢れさせません。column(system ビュー限定)と異なり、本ヒントは system / drill-down ビューおよび org の member grid で有効です。deploy ビューもグリッドを自動 バランスしますが、コンテナを realizes 先でグループ化する都合上コンテナノードが無く、 v1 では grid-columns による上書きはできません。

正の整数でない値(02.5 など)は style-grid-columns-invalid-value 警告とともに 破棄され、レイアウトは自動バランスにフォールバックします。

Related TPLs: TPL-20260510-21 — 一度に見せる範囲を限定し、単一ビューが一目で把握できる解像度を保つ(バランス grid は視覚密度を一定に保つ)。

directionauto | up | down | left | right

Section titled “direction — auto | up | down | left | right”

エッジに対するレイアウトヒント。エッジを視覚的にどの方向に流したいかを 示唆する。デフォルトは auto(エンジンに任せる)。

edge[write] { direction: down; }
edge[read] { direction: right; }
edge#criticalWrite { direction: down; }

値はリゾルバを経由して ResolvedEdgeStyle.direction に届き、GUI 編集 フロー(#1076 / #1098)と karasu の layered layout の両方で使われる。

  • auto(デフォルト): バイアスなし。エンジンに完全に任せる
  • up: source を target の に配置し、矢印が視覚的に上向きに 流れるようにする。トポロジカルなレイヤ割り当てでエッジを反転する か、forced kind-based system view では source を target の 1 段下に ずらすことで実現する。矢印自体の from -> to 方向は変わらない
  • down: source を target の に配置し、矢印が視覚的に下方向に 流れるようにする。バックエッジや forced kind-based 段組などで他の 制約が逆方向にレイアウトしようとしても、明示的に down で 上書きできる。up の鏡像で、forced layout では source を target の 1 段上に押し上げる(target 自身と他の同種ノードは動かない)。 target が既に layer 0 にある場合(押し上げる余地がない)は no-op で 自然な orientation に戻る。drill-down view(forced layer なし)では 自然な topological order が既に down を満たすので、auto と 観察上同じ
  • left / right: 矢印を / に流す(up / down と 同じく「矢印の流れる向き」を値で指定する)。source endpoint は 矢印の流れと逆側に配置される — direction: right は source を target の に、direction: left は source を target の に置く(結果として矢印は反対側に流れる)。自然な layered layout で source / target が異なる row に分かれる場合(service 同士の edge など 典型的なケース)、エンジンは まず source を target の layer に 引き寄せ、その後 within-layer の並び替えを行う。up / down の 「source 局所変位」モデルと同じ。bucketByColumn の後段で実行される ため、source endpoint については node column ヒントを上書きする (target の column は尊重)。同じ source への矛盾するヒントは last-wins で、cascade 規約と一貫する。詳細は docs/design/edge-direction-horizontal.md

サイクル / forced-layer フォールバック

Section titled “サイクル / forced-layer フォールバック”

up は absolute 指定ではなくヒント。以下のケースでエンジンは反転を 無効化する:

  • サイクルガード: up を適用すると layer DAG にサイクルが発生する 場合、該当エッジの反転を無効化し、自然な orientation で描画する
  • Forced kind-based layouts: トップレベルの system view は user → client → service → ... のような種別による段組を強制する。 ここでも direction: up は honor され、source ノードを target の 1 段下にずらす 形で実現する(target 自身と他の同種ノードは 動かない)。明示された該当エッジに限ってのみ kind stratification が 乱れる

詳細は docs/design/edge-direction-style.md

不正値は黙って破棄され、directionauto にフォールバックする。

label-positionstart | middle | end | <0.0..1.0>

Section titled “label-position — start | middle | end | <0.0..1.0>”

エッジに沿って label アンカーがどこに置かれるかを指定する。デフォルトは middle(= 0.5)。

edge[delivers] { label-position: start; } /* source 端寄り */
edge[implicit] { label-position: end; } /* target 端寄り */
edge#criticalWrite { label-position: 0.25; }

値がデフォルト(0.5)かつ label-offset0 のときは「最長セグメント の中点」ヒューリスティクスを保持し、既存図の出力は byte-stable のまま。 著者がいずれかを設定した時点で、polyline 全長を辿って position × totalLength の点をアンカーにする経路に切り替わる。

不正値(未知のキーワード、数値でない文字列)は middle にフォールバック。 [0, 1] 範囲外の小数値はクランプ。

label-offset<dy>px または <dx>px <dy>px

Section titled “label-offset — <dy>px または <dx>px <dy>px”

label アンカーを画面の x/y 軸方向にずらす値(pixel)。CSS shorthand の構文を踏襲:

  • 1 値 (label-offset: 8px) → dx = 0, dy = 8。最頻出の 「label を下方向にずらす」ケース
  • 2 値 (label-offset: 4px 8px) → dx = 4, dy = 8
edge { label-offset: 0 8px; } /* 全 label を anchor から 8px 下に */
edge#wide { label-offset: 4px 8px; }

screen axis(edge perpendicular ではなく)なので、グローバルルールでも edge の傾きに関係なく統一された方向にシフトする。正の値は右 (x) / 下 (y)、負の値は左 / 上。

renderer が anchor の上 -6px に label を置く既存のオフセットとは独立。 typographic な lift はそのまま、その上にこの offset が加算される。

以前の draft(撤回): 初版は label-offset を edge 方向に対する 1 軸 perpendicular ずらしと定義していた。これだと edge { label-offset: 8px; } の効果が edge の傾きごとに違う方向に出て 予測が立てにくかった。screen-axis CSS shorthand に切り替えた。詳細は ADR-20260509-05


  • グローバルスコープ(ファイル全体に適用)
  • 同じセレクタが複数ファイルで定義された場合は後勝ち
  • 衝突時は警告を出力(エラーにはしない)
⚠ Warning: セレクタ "service" が複数ファイルで定義されています
- default.krs.style:3
- my-theme.krs.style:2
my-theme.krs.style の定義が適用されます(後勝ち)

function resolveStyle(node, rules) {
return rules
.filter(rule => matches(node, rule.selector))
.sort((a, b) => specificity(a.selector) - specificity(b.selector))
.reduce((acc, rule) => ({ ...acc, ...rule.style }), {})
}
function specificity(selector) {
let score = 0
if (selector.id) score += 100
score += selector.tags.length * 10
score += selector.annotations.length * 10
if (selector.type) score += 1
return score
}

/* ── 種別セレクタ ── */
user {
background-color: #1D4ED8;
color: #DBEAFE;
border-color: #1E40AF;
border-width: 2px;
border-radius: 8px;
font-size: 13px;
font-weight: bold;
shape: user;
}
service {
background-color: #0369A1;
color: #E0F2FE;
border-color: #075985;
border-width: 2px;
border-radius: 8px;
font-size: 13px;
font-weight: bold;
shape: box;
}
domain {
background-color: #15803D;
color: #D1FAE5;
border-color: #166534;
shape: box;
}
usecase {
background-color: #1F2937;
color: #F9FAFB;
border-color: #374151;
font-size: 11px;
shape: box;
}
impl {
background-color: #78350F;
color: #FEF3C7;
border-color: #92400E;
shape: box;
}
/* ── タグセレクタ ── */
[external] {
background-color: #1F2937;
color: #D1D5DB;
border-color: #374151;
border-style: dashed;
}
/* ── アノテーションセレクタ ── */
@deprecated {
badge-color: #EF4444;
badge-icon: "⚠";
badge-label: "非推奨";
opacity: 0.6;
}
@new {
badge-color: #10B981;
badge-icon: "✦";
badge-label: "NEW";
}
@experimental {
badge-color: #F59E0B;
badge-icon: "⚗";
badge-label: "実験的";
}
@migration_target {
badge-color: #3B82F6;
badge-icon: "→";
badge-label: "移行先";
}
/* ── 複合セレクタ ── */
user[external] {
color: #9CA3AF;
}
[external]@deprecated {
border-color: #EF4444;
}
/* ── IDセレクタ ── */
#ECommerce {
background-color: #7C3AED;
}
/* ── エッジ ── */
edge {
color: #94A3B8;
stroke-width: 1.5px;
font-size: 11px;
}
edge[async] {
border-style: dashed;
color: #6B7280;
}
/* ── 組織図(Org Tree View)── */
team {
background-color: #1E3A5F;
color: #E2E8F0;
border-color: #3B82F6;
}
member {
background-color: #0F172A;
border-color: #334155;
}
/* 特定チームのみ強調 */
#BackendTeam {
border-color: #F59E0B;
border-width: 2px;
}

組織図ノードセレクタ(Org Tree View)

Section titled “組織図ノードセレクタ(Org Tree View)”

Org Tree View は team / member の種別セレクタと ID セレクタ(#NodeId)をサポートします。

セレクタ対象
teamすべてのチームカード
memberすべてのメンバーカード
#TeamId特定のチームカード
#MemberId特定のメンバーカード
edgeチーム間のベジェコネクタ

対応プロパティ:

プロパティ効果
background-colorカード背景色
colorテキスト色
border-color枠線色
border-width枠線幅(px)
border-radius角丸(px)
font-sizeフォントサイズ(px)
font-weightフォントウェイト(normal / bold
font-familyフォントファミリー

注意: opacity / shape / badge-* は Org Tree View では無視されます。 タグ・アノテーション複合セレクタ(team[external] 等)は現時点では未サポートです。

© 2026 Hiroki Kondo · Licensed under Apache-2.0