Open26

CSS Architecture 翻訳

つきやまつきやま

To many Web developers, being good at CSS means you can take a visual mock-up and replicate it perfectly in code. You don’t use tables, and you pride yourself on using as few images as possible. If you’re really good, you use the latest and greatest techniques like media queries, transitions and transforms. While all this is certainly true of good CSS developers, there’s an entirely separate side to CSS that rarely gets mentioned when assessing one’s skill.

多くのウェブ開発者にとって、CSSが得意であるということは、視覚的なモックアップをコードで完璧に再現できることを意味する。テーブルを使わず、画像をできるだけ使わないことに誇りを持っている。本当に優秀なら、メディアクエリやトランジション、トランスフォームといった最新かつ最高のテクニックを使う。これらすべてが優れたCSS開発者に当てはまるのは確かですが、CSSにはまったく別の側面があります。

つきやまつきやま

Interestingly, we don’t usually make this oversight with other languages. A Rails developer isn’t considered good just because his code works to spec. This is considered baseline. Of course it must work to spec; its merit is based on other things: Is the code readable? Is it easy to change or extend? Is it decoupled from other parts of the application? Will it scale?

興味深いことに、他の言語では通常このような見落としはありません。Rails開発者は、コードが仕様どおりに動くからといって優秀とはみなされません。これはベースラインと見なされます。もちろん仕様どおりに動作しなければなりません: コードが読みやすいか。コードの変更や拡張は容易か?アプリケーションの他の部分から切り離されているか?拡張性はあるか?など、ほかの言語では関心が異なります。

つきやまつきやま

These questions are natural when assessing other parts of the code base, and CSS shouldn’t be any different. Today’s web applications are larger than ever, and a poorly thought-out CSS architecture can cripple development. It’s time to evaluate CSS the same way we evaluate every other part of the application. It cannot be an afterthought or written off as merely the designer’s problem.

このような疑問は、コードベースの他の部分を評価するときに当然のことであり、CSSも同じであるべきです。今日のウェブ・アプリケーションはかつてないほど大規模になっており、CSSアーキテクチャの思慮が浅いと、開発に支障をきたす可能性があります。アプリケーションの他のすべての部分を評価するのと同じように、CSSを評価する時が来たのです。CSSを後回しにしたり、単なるデザイナーの問題として片付けてはいけないのです。

つきやまつきやま

The Goals of Good CSS Architecture

In the CSS community, a general consensus of best practices is very difficult to come by. Judging purely by the comments on Hacker News and the reaction of developers to the release of CSS Lint, it’s clear that many people disagree over even the basic things CSS authors should and shouldn’t do.

So instead of laying out an argument for my own set of best practices, I think we should start by defining our goals. If we can agree upon the goals, hopefully we can start to spot bad CSS not because it breaks our preconceived notions of what’s good but because it actually hinders the development process.

I believe the goals of good CSS architecture shouldn’t be that different from the goals of all good software development. I want my CSS to be predictable, reusable, maintainable, and scalable.

優れたCSSアーキテクチャの目標

CSSコミュニティでは、ベストプラクティスに関する一般的なコンセンサスを得ることは非常に困難です。Hacker Newsに寄せられたコメントや、CSS Lintのリリースに対する開発者の反応から判断しても、CSSの作者がすべきこと、すべきでないことの基本的なことでさえ、多くの人が意見が一致しないことは明らかです。

なので、私なりのベストプラクティスの議論を展開する代わりに、まずはゴールを定義することから始めるべきだと思います。ゴールに合意できれば、先入観にとらわれることなく、悪いCSSを見抜くことができるようになります。

私は、優れたCSSアーキテクチャの目標は、すべての優れたソフトウェア開発の目標とそれほど違わないはずだと信じています。私は、CSSが予測可能で、再利用可能で、メンテナンス可能で、スケーラブルであることを望んでいます。

つきやまつきやま

Predictable

Predictable CSS means your rules behave as you’d expect. When you add or update a rule, it shouldn’t affect parts of your site that you didn’t intend. On small sites that rarely change, this isn’t as important, but on large sites with tens or hundreds of pages, predictable CSS is a must.

予測可能

予測可能なCSSとは、ルールが期待通りに動作することを意味します。ルールを追加したり更新したりしても、意図しない部分に影響が及ぶことはありません。めったに変更しない小さなサイトでは、これはそれほど重要ではありませんが、何十、何百ページもある大きなサイトでは、予測可能なCSSは必須です。

つきやまつきやま

Reusable

CSS rules should be abstract and decoupled enough that you can build new components quickly from existing parts without having to recode patterns and problems you’ve already solved.

再利用可能

CSSのルールは抽象的で、すでに解決したパターンや問題を再コード化することなく、既存のパーツから新しいコンポーネントを素早く構築できるように、十分に分離されていなければならない。

つきやまつきやま

Maintainable

When new components and features need to be added, updated or rearranged on your site, doing so shouldn’t require refactoring existing CSS. Adding component X to the page shouldn’t break component Y by its mere presence.

保守性

サイトに新しいコンポーネントや機能を追加、更新、再配置する必要がある場合、既存のCSSをリファクタリングする必要はありません。ページにコンポーネントXを追加しても、その存在だけでコンポーネントYが壊れてしまうようなことがあってはなりません。

つきやまつきやま

Scalable

As your site grows in size and complexity it usually requires more developers to maintain. Scalable CSS means it can be easily managed by a single person or a large engineering team. It also means your site’s CSS architecture is easily approachable without requiring an enormous learning curve. Just because you’re the only developer touching the CSS today doesn’t mean that will always be the case.

拡張可能

サイトの規模が大きくなり、複雑化すると、通常、保守に多くの開発者が必要になります。スケーラブルCSSは、一人でも大規模なエンジニアリングチームでも簡単に管理できることを意味します。また、サイトのCSSアーキテクチャーは、膨大な学習曲線を必要とせず、簡単にアプローチできるということでもあります。今日、CSSを触っている開発者があなただけだからといって、それが常にそうであるとは限りません。

つきやまつきやま

Common Bad Practices

Before we look at ways to achieve the goals of good CSS architecture, I think it can be helpful to look at common practices that get in the way of our goals. It’s often only through repeated mistakes that we can begin to embrace an alternate path.

The following examples are all generalizations of code I’ve actually written, and, while technically valid, each has lead to disaster and headache. Dispite my best intentions and the promise that this time would be different, these patterns consistently got me into trouble.

一般的な悪習

優れたCSSアーキテクチャの目標を達成する方法を検討する前に、目標の妨げとなる一般的な慣行を検討することは有益だと思います。失敗を繰り返してこそ、別の道を受け入れることができるのです。

以下の例はすべて、私が実際に書いたコードの一般化であり、技術的には妥当だが、それぞれが災難と頭痛の種をもたらした。私の善意と「今回は違うぞ」という約束にもかかわらず、これらのパターンは一貫して私をトラブルに陥れた。

つきやまつきやま

Modifying Components Based On Who Their Parents Are

In almost every site on the web there will be a particular visual element that looks exactly the same with each occurrence, except one. And when faced with this one-off situation almost every new CSS developer (and even experienced ones) handles it the same way. You figure out some unique parent for this one particular occurrence (or you create one), and you write a new rule to handle it.

親が誰であるかによってコンポーネントを変更する

ウェブ上のほとんどすべてのサイトで、1つを除いて、発生するたびにまったく同じに見える特定の視覚要素があります。そして、このような一度きりの状況に直面したとき、ほとんどすべての新米CSS開発者(そして経験豊富な開発者でさえも)が同じように対処します。この1つだけしかない特別な親要素を見つけ出し(あるいは親要素を作成し)、それを処理するための新しいルールを書きます。

.widget {
  background: yellow;
  border: 1px solid black;
  color: black;
  width: 50%;
}

#sidebar .widget {
  width: 200px;
}

body.homepage .widget {
  background: white;
}

At first this might seem like fairly harmless code, but let’s examine it based on the goals established above.

最初は、これはかなり無害なコードに見えるかもしれないが、上で設定した目標に基づいて検証してみよう。

First, the widget in the example is not predictable. A developer who’s made several of these widgets will expect it to look a certain way, yet when she uses it in the sidebar or on the homepage, it will look different, despite the markup being exactly the same.

まず、例のウィジェットは予測できません。このようなウィジェットをいくつも作ってきた開発者は、ウィジェットがある特定の方法で見えることを期待するでしょう。しかし、サイドバーやホームページで使用すると、マークアップはまったく同じであるにもかかわらず、違って見えます。

It’s also not very reusable or scalable. What happens when the way it looks on the homepage is requested on some other page? New rules will have to be added.

また、再利用性や拡張性にも乏しい。ホームページでの見え方が、他のページで要求されたらどうなるのか?新しいルールを追加しなければならない。

Lastly, it’s not easily maintainable because if the widget were to get redesigned, it would have to get updated in several places in the CSS, and unlike the above example, the rules that commit this particular anti-pattern rarely appear right next to each other.

最後に、ウィジェットのデザインが変更された場合、CSSの数カ所を更新する必要があり、上記の例とは異なり、この特定のアンチパターンを犯すルールが互いに隣り合うことはほとんどないため、メンテナンスが容易ではありません。

Imagine if this type of coding were done in any other language. You’re essentially making a class definition, and then in another part of the code you’re reaching into that class definition and changing it for a particular use case. This directly violates the open/closed principle of software development:

このようなコーディングが他の言語で行われるとしたらどうだろう。あなたは本質的にクラス定義を行い、コードの別の部分でそのクラス定義に手を伸ばし、特定のユースケースのために変更しているのだ。これは、ソフトウェア開発のオープン/クローズの原則に直接違反している:

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

ソフトウェア・エンティティ(クラス、モジュール、ファンクションなど)は、拡張に対してはオープンであるべきだが、変更に対してはクローズであるべきだ。

Later in this article we’ll look at how to modify components without relying on parent selectors.

この記事の後半では、親セレクタに頼らずにコンポーネントを変更する方法を見ていく。

つきやまつきやま

Overly Complicated Selectors

Occasionally an article will make its way around the Internet showcasing the power of CSS selectors and proclaiming that you can style an entire site without using any classes or IDs.

複雑すぎるセレクター

時折、CSS詳細度を紹介し、クラスやIDを使わずにサイト全体をスタイリングできると宣言する記事がインターネットを駆け巡ることがある。

While technically true, the more I develop with CSS, the more I stay away from complex selectors. The more complicated a selector the more coupled it is to the HTML. Relying on HTML tags and combinators keeps your HTML squeaky clean, but it makes your CSS gross and dirty.

技術的には正しいのだが、CSSを開発すればするほど、複雑なセレクタには近づかなくなる。セレクタが複雑であればあるほど、HTMLとの結びつきが強くなるからだ。HTMLタグとコンビネーターに頼ると、HTMLはきれいに保たれるが、CSSは汚くなる。

#main-nav ul li ul li div { }
#content article h1:first-child { }
#sidebar > div > h3 + p { }

All of the above examples make logical sense. The first is probably styling a dropdown menu, the second says that the article’s main heading should look different from all other <h1> elements, and the last example is likely adding some extra spacing for the first paragraph in the sidebar sections.

上記の例はすべて論理的に理にかなっています。最初の例はおそらくドロップダウンメニューのスタイリングであり、2番目の例は記事の主見出しが他のすべての<h1>要素とは異なって見えるべきであると言っています。

If this HTML were never going to change, an argument could be made for its merits, but how realistic is it to assume the HTML will never change? Overly complicated selectors can be impressive and they can go far to rid the HTML of presentational hooks, but they rarely help us achieve our goals for good CSS architecture.

このHTMLが変わることがないのであれば、そのメリットを主張することもできるだろうが、HTMLが変わることがないと仮定することがどれほど現実的だろうか。過度に複雑なセレクタは印象的であり、HTMLから体裁的なフックを取り除くのに大いに役立ちますが、優れたCSSアーキテクチャの目標達成に役立つことはほとんどありません。

These examples above are not reusable at all. Since the selector is pointing to a very particular place in the markup, how could another component with a different HTML structure reuse those styles? Taking the first selector (the dropdown) as an example, what if a similar looking dropdown were needed on a different page and it wasn’t inside of the #main-nav element? You’d have to recreate the entire style.

上の例はまったく再利用できません。セレクタはマークアップ内の非常に特定の場所を指しているので、異なるHTML構造を持つ別のコンポーネントがこれらのスタイルを再利用できるでしょうか?最初のセレクタ(ドロップダウン)を例にとると、同じような見た目のドロップダウンが別のページで必要になり、それが#main-nav要素の中になかったらどうでしょう?スタイル全体を作り直す必要があります。

These selectors are also very unpredictable if the HTML needs to change. Imagine that a developer wanted to change the <div> in the third example to the HTML5 <section> tag, the whole rule would break.

これらのセレクタはまた、HTMLを変更する必要がある場合、非常に予測困難です。もし開発者が3つ目の例の<div>をHTML5の<section>タグに変えたいと思ったします。

Finally, since these selectors only work when the HTML remains constant, they’re by definition not maintainable or scalable.

最後に、これらのセレクタはHTMLが一定の場合にのみ機能するため、定義上、保守性や拡張性に欠けます。

In large applictaions you have to make trade-offs and compromises. The fragility of complex selectors are rarely worth the price in the name of keeping your HTML “clean”.

大規模なアプリケーションでは、トレードオフと妥協をしなければなりません。複雑なセレクタの壊れやすさは、HTMLを "クリーン "に保つという大義名分の代償に見合うものではありません。

つきやまつきやま

Overly Generic Class Names

When creating reusable design components, it’s very common to scope (as it were) the component’s sub-elements inside the component’s class name. For example:

過度に一般的なクラス名

再利用可能なデザイン・コンポーネントを作成する際、コンポーネントのクラス名の中にコンポーネントのサブ要素を(いわば)スコープすることはよくあることです。例えば

<div class="widget">
  <h3 class="title">...</h3>
  <div class="contents">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    In condimentum justo et est dapibus sit amet euismod ligula ornare.
    Vivamus elementum accumsan dignissim.
    <button class="action">Click Me!</button>
  </div>
</div>
.widget {}
.widget .title {}
.widget .contents {}
.widget .action {}

The idea is that the .title, .contents, and .action sub-element classes can be safely styled without having to worry about those styles spilling over to any other elements styled with the same classes. This is true, but it doesn’t prevent the styling of classes with those same names from spilling into this component.

.title.contents.action サブ要素クラスは、同じクラスでスタイリングされた他の要素にスタイルが波及することを心配することなく、安全にスタイリングできるという考え方です。これは事実ですが、同じ名前のクラスのスタイルがこのコンポーネントに波及するのを防ぐことはできません。

On a large project it’s very likely that a class name like .title would get used in another context or even by itself. If that happened, the widget’s title would suddenly look very different than intended.

大規模なプロジェクトでは、.title のようなクラス名が別のコンテキストで使われたり、単独で使われたりする可能性が非常に高いです。そのような場合、ウィジェットのタイトルは突然、意図したものとはまったく異なるものになります。

Overly generic class names lead to very unpredictable CSS.

あまりにも一般的なクラス名は、予測不可能なCSSを生み出します。

つきやまつきやま

Making a Rule Do Too Much

Sometimes you make a visual component that needs to be 20 pixels from the top left corner of a section in your site:

ルールを作りすぎる

サイトのセクションの左上隅から20ピクセルの位置にビジュアル・コンポーネントを配置する必要がある場合があります:

.widget {
  position: absolute;
  top: 20px;
  left: 20px;
  background-color: red;
  font-size: 1.5em;
  text-transform: uppercase;
}

Then down the road you need to use this exact same component in a different location. The above CSS won’t work because it’s not reusable in different contexts.

次に、別の場所でまったく同じコンポーネントを使う必要が出てきます。上記のCSSは、異なるコンテキストで再利用できないため、機能しません。

The problem is that you’re making this one selector do too much. You’re defining the look and feel as well as the layout and position within the same rule. The look and feel is reusable but the layout and position is not. And since they’re used together, the whole rule is compromised.

問題は、この1つのセレクタに多くのことをさせていることだ。同じルールの中で、ルック&フィールとレイアウトと位置を定義している。ルック&フィールは再利用可能ですが、レイアウトと位置はそうではありません。そして、これらは一緒に使われているため、ルール全体が危険にさらされています。

While this may seem harmless at first, it often leads to copying and pasting from less CSS-savvy developers. If a new team member wants something to look like a particular component, say an .infobox, they’ll probably start by trying that class. But if that doesn’t work because it positions that new infobox in an undesired way, what are they likely to do? In my experience, most new developers will not break the rule up into its reusable parts. Instead they’ll simply copy and paste the lines of code needed for this particular instance into a new selector, unnecessarily duplicating code.

これは最初は無害に見えるかもしれませんが、CSSにあまり詳しくない開発者がコピー&ペーストすることによくつながります。新しいチームメンバーが特定のコンポーネント、例えば.infoboxのように見せたい場合、おそらくそのクラスを試すことから始めるでしょう。しかし、その新しいinfoboxが望ましくない位置にあるためにうまくいかないとしたら、彼らはどうするでしょうか?私の経験では、ほとんどの新しい開発者は、ルールを再利用可能な部分に分割しません。その代わりに、この特定のインスタンスに必要なコード行を新しいセレクタにコピー&ペーストするだけで、不必要にコードが重複してしまいます。

つきやまつきやま

The Cause

All of the above bad practices share one similarity, they place far too much of the styling burden on the CSS.

原因

上記の悪習慣には共通点があり、CSSにスタイリングの負担をかけすぎているという点です。

That may seem like a strange statement. After all, it is a stylesheet; shouldn’t it bear most (if not all) of the styling burden? Isn’t that what we want?

奇妙な発言に思えるかもしれませんが。結局のところ、それはスタイルシートなのだから、(すべてではないにせよ)スタイリングの重荷のほとんどを負うべきではないだろうか?それが私たちの望むことではないのか?

The simple answer to this question is “yes”, but, as usual, things aren’t always so simple. Separating content from presentation is a good thing, but just because your CSS is separate from your HTML doesn’t mean your content is separate from your presentation. Put another way, striping all presentational code from your HTML doesn’t fulfill the goal if your CSS requires an intimate knowledge of your HTML structure in order to work.

この質問に対するシンプルな答えは「イエス」だが、いつものように、物事は必ずしもそう単純ではないです。コンテンツとプレゼンテーションを分離することは良いことだが、CSSがHTMLから分離されているからといって、コンテンツがプレゼンテーションから分離されているとは限らない。別の言い方をすれば、HTMLからプレゼンテーション用のコードをすべて取り除いたとしても、CSSが機能するためにHTMLの構造を熟知していなければならないのであれば、その目的は達成されません。

Furthermore, HTML is rarely just content; it’s almost always structure too. And often that structure consists of container elements with no purpose other than to allow the CSS to isolate a certain group of elements. Even without presentational classes, this is still clearly presentation mixed into the HTML. But is it necessarily mixing presentation with content?

さらに、HTMLが単なるコンテンツであることはほとんどなく、ほとんどの場合、構造も含んでいます。そして多くの場合、その構造は、CSSが特定の要素群を分離できるようにする以外の目的を持たないコンテナ要素で構成されています。プレゼンテーション・クラスがなくても、これは明らかにHTMLにプレゼンテーションが混ざっています。しかし、必ずしもプレゼンテーションとコンテンツが混在しているのでしょうか?

I believe, given the current state of HTML and CSS, it’s necessary and often wise to have the HTML and CSS work together as a presentational layer. The content layer can still be abstracted away via templates and partials.

私は、HTMLとCSSの現状を考えると、HTMLとCSSをプレゼンレイヤーとして一緒に機能させることが必要であり、しばしば賢明であると考えています。コンテンツレイヤーは、テンプレートやパーシャルによって抽象化することができます。

つきやまつきやま

The Solution

If your HTML and your CSS are going to work together to form the presentation layer of a web application, they need to do so in a way that promotes all of the principles of good CSS architecture.

解決策

HTMLとCSSが一緒になってウェブ・アプリケーションのプレゼンテーション・レイヤーを形成するのであれば、優れたCSSアーキテクチャーの原則をすべて促進するような方法で行う必要があります。

The best approach that I’ve found is for the CSS to assume as little HTML structure as possible. The CSS should define how a set of visual elements look and (in order to minimize coupling with the HTML) those elements should look as they’re defined regardless of where they appear in the HTML. If a certain component needs to look different in a different scenario, it should be called something different and it’s the HTML’s responsibility to call it that.

私が見つけた最良のアプローチは、CSSができるだけHTMLの構造を前提としないことだ。CSSは、一連の視覚的要素がどのように見えるかを定義すべきであり、(HTMLとの結合を最小限にするために)それらの要素は、HTMLのどこに表示されるかに関係なく、定義されたとおりに見えるべきである。あるコンポーネントが異なるシナリオで異なる外観を持つ必要がある場合、それは別の何かと呼ばれるべきであり、そう呼ぶのはHTMLの責任です。

As an example, the CSS might define a button component via the .button class. If the HTML wants a particular element to look like a button, it should use that class. If there’s a situation were the button needs to look different (perhaps larger and full-width), then the CSS needs to define that look as well with a new class, and the HTML can include that new class to employ the new look.

例として、CSSは.buttonクラスを使ってボタン・コンポーネントを定義するかもしれない。HTMLが特定の要素をボタンのように見せたいなら、そのクラスを使うべきです。もし、ボタンが異なる外観(おそらく、より大きく、全幅)を必要とする状況があれば、CSSは新しいクラスでその外観も定義する必要があり、HTMLは新しい外観を採用するためにその新しいクラスを含めることができます。

The CSS defines what your components look like, and the HTML assigns those looks to the elements on the page. The less the CSS needs to know about the HTML structure the better.

CSSはコンポーネントの外観を定義し、HTMLはその外観をページ上の要素に割り当てます。CSSがHTMLの構造について知る必要は、少なければ少ないほどよいです。

A huge benefit of declaring exactly what you want in the HTML is it allows other developers to look at the markup and know exactly what the element is supposed to look like. The intent is obvious. Without this practice it’s impossible to tell if the look of an element is intentional or accidental, and this leads to confusion on the team.

HTMLの中で欲しいものを正確に宣言することの大きな利点は、他の開発者がマークアップを見て、その要素がどのように見えるべきかを正確に知ることができるということだ。意図は明白だ。この習慣がないと、要素の見た目が意図的なものなのか偶然なのかを見分けることができず、チーム内の混乱につながります。

A common objection to putting a lot of classes in the markup is the extra effort required to do so. A single CSS rule could target a thousand instances of a particular component. Is it really worth writing that classes a thousand times just to have it explicitly declared in the markup?

マークアップに多くのクラスを記述することに対する一般的な反対意見は、そのために必要な余分な労力である。1つのCSSルールが、特定のコンポーネントの1000のインスタンスを対象とする可能性がある。マークアップで明示的に宣言するためだけに、そのクラスを1000回も書く価値が本当にあるのでしょうか?

While this concern is clearly valid, it can be misleading. The implication is that either you use a parent selector in the CSS or you write that HTML class 1000 times by hand, but there are obviously other alternatives. View level abstractions in Rails or other frameworks can go a long way toward keeping the visual look explicitly declared in the HTML without having to write the same class over and over again.

この懸念は明らかに妥当だが、誤解を招く恐れがある。CSSで親セレクタを使うか、HTMLのクラスを1000回手で書くかのどちらかだという意味合いですが、明らかに他の選択肢もあります。Railsや他のフレームワークのビューレベル抽象化機能を使えば、同じクラスを何度も書くことなく、HTMLで視覚的な外観を明示的に宣言し続けることができます。

つきやまつきやま

Best Practices

After making the above mistakes over and over again, and paying the consequences later on down the road, I’ve come up with the following bits of advice. While by no means comprehensive, my experience has shown that sticking to these principles will help you better achieve the goals of good CSS architecture.

ベストプラクティス

上記のような失敗を何度も何度も繰り返し、後々そのツケを払ってきた経験から、私は以下のようなアドバイスを思いついた。決して包括的なものではありませんが、私の経験から、これらの原則を守ることで、優れたCSSアーキテクチャの目標をよりよく達成できることがわかりました。

つきやまつきやま

Be intentional

The best way to make sure your selectors don’t style unwanted elements is to not give them the opportunity. A selector like #main-nav ul li ul li div could very easily end up applying to unwanted elements as your markup changes down the road. A style like .subnav, on the other hand, will have absolutely no chance of accidentally applying to an unwanted element. Applying classes directly to the elements you want to style is the best way to keep your CSS predictable.

意図的に

セレクタが不要な要素をスタイルしないようにする最善の方法は、セレクタにその機会を与えないことです。main-nav ul li ul li divのようなセレクタは、マークアップの変更に伴って不要な要素に適用されてしまう可能性があります。一方、.subnavのようなスタイルは、誤って不要な要素に適用される可能性はまったくありません。スタイルを設定したい要素に直接クラスを適用することが、CSSを予測しやすくする最善の方法です。

/* Grenade */
#main-nav ul li ul { }

/* Sniper Rifle */
.subnav { }

Given the two examples above, think of the first one like a grenade and the second like a sniper rifle. The grenade might work just fine today, but you never know when an innocent civilian could move inside the blast radius.

上の2つの例で考えると、1つ目は手榴弾、2つ目はスナイパーライフルのようなものだ。手榴弾は現在では問題なく使えるかもしれないが、いつ罪のない一般市民が爆風圏内に移動してくるかわからない。

つきやまつきやま

Separate your concerns

I’ve already mentioned that a well organized component layer can help loosen the coupling of HTML structure in the CSS. In addition to that, your CSS components themselves should be modular. Components should know how to style themselves and do that job well, but they should not be responsible for their layout or positioning nor should they make too many assumptions about how they’ll be spaced in relation to surrounding elements.

懸念事項を分ける

よく整理されたコンポーネント・レイヤーが、CSSにおけるHTML構造の結合を緩めるのに役立つことはすでに述べた。それに加えて、CSSコンポーネント自体もモジュール化されるべきです。コンポーネントは、それ自身がどのようにスタイル付けされ、その仕事をうまくこなすかを知っているべきですが、レイアウトや配置に責任を持つべきではなく、また、周囲の要素との関係でどのように間隔を空けるかについて、多くの仮定を持つべきではないのです。

In general, components should define how they look, but not their layout or position. Be careful when you see properties like background, color, and font in the same rule as position, width, height, and margin.

一般的に、コンポーネントはどのように見えるかを定義すべきですが、レイアウトや位置を定義すべきではありません。background、color、fontといったプロパティが、position、width、height、marginと同じルールに含まれている場合は注意が必要です。

Layout and position should be handled by either a separate layout class or a separate container element. (Remember that to effectively separate content from presentation it’s often essential to separate content from its container.)

レイアウトと位置は、別のレイアウト・クラスか別のコンテナ要素で扱うべきです。(コンテンツとプレゼンテーションを効果的に分離するためには、コンテナからコンテンツを分離することがしばしば不可欠であることを覚えておいてください)。

つきやまつきやま

Namespace your classes

We already examined why parent selectors aren’t 100% effective at encapsulation and preventing style cross-contamination. A much better approach is applying namespaces to the classes themselves. If an element is a member of a visual component, every one of its sub-element classes should use the component’s base class name as a namespace.

クラスの名前空間

親セレクタがカプセル化とスタイルの相互汚染を防ぐのに100%効果的でない理由はすでに説明しました。より良い方法は、クラス自体に名前空間を適用することです。要素がビジュアル・コンポーネントのメンバーである場合、そのサブ要素のクラスはすべて、名前空間としてコンポーネントのベース・クラス名を使用する必要があります。

/* High risk of style cross-contamination */
.widget { }
.widget .title { }

/* Low risk of style cross-contamination */
.widget { }
.widget-title { }

Namespacing your classes keeps your components self-contained and modular. It minimizes the likelihood that an existing class will conflict, and it lowers the specificity required to style child elements.

クラスに名前を付けることで、コンポーネントが自己完結し、モジュール化されます。既存のクラスが衝突する可能性を最小限に抑え、子要素のスタイルに必要な特殊性を低くします。

つきやまつきやま

Extend components with modifier classes

When an existing component needs to look slightly different in a certain context, create a modifier class to extend it.

修飾クラスでコンポーネントを拡張する

既存のコンポーネントが、特定の文脈で少し異なる外観を持つ必要がある場合、それを拡張する修飾クラスを作成する。

/* Bad */
.widget { }
#sidebar .widget { }

/* Good */
.widget { }
.widget-sidebar { }

We’ve already seen the downsides of modifying components based on one of their parent elements, but to reiterate: A modifier class can be used anywhere. Location based overrides can only be used in a specific location. Modifier classes can also be reused as many times as you need. Lastly, modifier classes express the intention of the developer very clearly right in the HTML. Location based classes, on the other hand, are completely invisible to a developer only looking at the HTML, greatly increasing the probability that it will be overlooked.

親要素の1つに基づいてコンポーネントを修正することの弊害はすでに見てきたが、もう一度言っておこう: モディファイア・クラスはどこでも使用できます。場所ベースのオーバーライドは、特定の場所でしか使用できません。モディファイア・クラスは何度でも再利用できます。最後に、モディファイア・クラスは開発者の意図をHTMLの中で明確に表現します。一方、ロケーションベースのクラスは、HTMLを見ているだけの開発者にはまったく見えないので、見落とされる可能性が非常に高くなります。

つきやまつきやま

Organize Your CSS Into a Logical Structure

Jonathan Snook, in his excellent book SMACSS, argues for organizing your CSS rules into four separate categories: base, layout, modules, and state. Base consists of reset rules and element defaults. Layout is for positioning of site-wide elements as well as generic layout helpers like grid systems. Modules are reusable visual elements, and state refers to styling that can be toggled on or off via JavaScript.

CSSを論理的な構造に整理する

ジョナサン・スヌック氏は、その優れた著書『SMACSS』の中で、CSSルールをベース、レイアウト、モジュール、ステートの4つに分けて整理することを主張している。ベースは、リセットルールと要素のデフォルトで構成されています。レイアウトは、サイト全体の要素の配置や、グリッドシステムのような一般的なレイアウト・ヘルパーのためのものです。モジュールは再利用可能なビジュアル要素で、ステートはJavaScriptでオン・オフを切り替えられるスタイリングを指します。

In the SMACSS system, modules (which are equivalent to what I call components) comprise the vast majority of all the CSS rules, so I often find it necessary to break them down even further into abstract templates.

SMACSSシステムでは、モジュール(私がコンポーネントと呼ぶものに相当する)がCSSルールの大部分を占めているので、私はしばしば、それらを抽象的なテンプレートにさらに分解する必要があると感じます。

Components are standalone visual elements. Templates, on the other hand, are building blocks. Templates don’t stand on their own and rarely describe look and feel. Instead, they’re single, repeatable patterns that can be put together to form a component.

コンポーネントは独立したビジュアル要素です。一方、テンプレートは構成要素です。テンプレートは単体では存在せず、ルック&フィールを記述することはほとんどありません。代わりに、コンポーネントを形成するために組み合わせることができる、単一の繰り返し可能なパターンです。

To provide a concrete example, a component might be a modal dialog box. The modal might have the site’s signature background gradient in the header, it might have a drop shadow around it, it might have a close button in the top right corner, and it might be positioned fixed and centered vertically and horizontally. Each of these four patterns might be used again and again all over the site, so you wouldn’t want to have to recode those patterns each time. As such they’re all templates, and together they comprise the modal component.

具体的な例を挙げると、コンポーネントはモーダルダイアログボックスかもしれません。モーダルには、サイトの特徴である背景のグラデーションがヘッダーにあり、周囲にドロップシャドウがあり、右上に閉じるボタンがあり、縦方向と横方向に固定されて中央に配置されるかもしれません。これら4つのパターンはそれぞれ、サイト全体で何度も何度も使用される可能性があるため、毎回これらのパターンを再コード化する必要はないだろう。したがって、これらはすべてテンプレートであり、モーダル コンポーネントを構成します。

I typically don’t use template classes in the HTML unless I have a good reason. Instead I use a preprocessor to include the template styles in the component definition. I’ll discuss this and my rational for doing so in more detail later.

私は通常、よほどの理由がない限り、HTMLにテンプレート・クラスを使用しない。その代わりに、プリプロセッサを使ってテンプレート・スタイルをコンポーネント定義に含めます。この方法とその理由については、後で詳しく説明します。

つきやまつきやま

Use Classes For Styling And Styling Only

Anyone who has worked on a large project has come across an HTML element with a class whose purpose was completely unknown. You want to remove it, but you’re hesitant because it may have some purpose that you’re not aware of. As this happens again and again, over time, your HTML become filled with classes that serve no purpose just because team members are afraid to delete them.

スタイリングとスタイリングにのみクラスを使う

大規模なプロジェクトに携わったことのある人なら誰でも、用途がまったくわからないクラスを持つHTML要素に出くわしたことがあるでしょう。削除したいが、自分の知らない目的があるかもしれないので躊躇してしまう。このようなことが何度も繰り返されるうちに、時間の経過とともに、チームメンバーが削除を恐れているばかりに、HTMLは何の役にも立たないクラスで埋め尽くされるようになる。

The problem is that classes are generally given too many responsibilities in front-end web development. They style HTML elements, they act as JavaScript hooks, they’re added to the HTML for feature detections, they’re used in automated tests, etc.

問題は、フロントエンドのウェブ開発において、クラスが一般的に多くの責任を負わされすぎていることだ。HTML要素のスタイルを整えたり、JavaScriptのフックとして機能したり、機能検出のためにHTMLに追加されたり、自動テストで使われたり、などなど。

This is a problem. When classes are used by too many parts of the application, it becomes very scary to remove them from your HTML.

これは問題だ。クラスがアプリケーションの多くの部分で使われるようになると、HTMLからそれらを削除するのがとても怖くなります。

However, with an established convention, this problem can be completely avoided. When you see a class in the HTML, you should be able to tell instantly what its purpose is. My recommendation is to give all non-styled classes a prefix. I use .js- for JavaScript and I use .supports- for Modernizr classes. All classes without a prefix are for styling and styling only.

しかし、確立された慣習があれば、この問題は完全に回避できる。HTMLの中でクラスを見かけたら、その目的が何なのかを即座に見分けられるようにすべきです。私が推奨するのは、スタイル指定されていないクラスにはすべて接頭辞をつけることだ。JavaScriptには.js-を、Modernizrのクラスには.supports-を使います。接頭辞のないクラスはすべて、スタイリングとスタイリング専用です。

This makes finding unused classes and removing them from the HTML as easy as searching the stylesheets directory. You can even automate this process in JavaScript by cross referencing the classes in the HTML with the classes in the document.styleSheets object. Classes that aren’t in document.styleSheets can be safely removed.

これにより、スタイルシート・ディレクトリを検索するのと同じくらい簡単に、未使用のクラスを見つけてHTMLから削除することができます。JavaScriptでは、HTML内のクラスとdocument.styleSheetsオブジェクト内のクラスを相互参照することで、このプロセスを自動化することもできます。document.styleSheetsにないクラスは安全に削除できます。

In general, just as it’s a best practice to separate your content from your presentation, it’s also important to separate your presentation from your functionality. Using styled classes as JavaScript hooks deeply couples your CSS and JavaScript in a way that can make it hard or impossible to update the look of certain elements without breaking functionality.

一般的に、コンテンツをプレゼンテーションから分離することがベストプラクティスであるのと同様に、プレゼンテーションを機能性から分離することも重要です。スタイル付きクラスを JavaScript のフックとして使用すると、CSS と JavaScript が深く結合され、機能を壊すことなく特定の要素の外観を更新することが難しくなるか、不可能になります。

つきやまつきやま

Name your classes with a logical structure

These days most people write CSS with hyphens as word separators. But hyphens alone are usually not enough to distinguish between different types of classes.

論理的な構造を持つクラス名をつける

最近では、ハイフンを単語の区切り文字として使ってCSSを記述する人がほとんどです。しかし、ハイフンだけでは通常、異なるタイプのクラスを区別するには不十分です。

Nicolas Gallagher recently wrote about his solution to this problem which I have also adopted (with slight changes) with great success. To illustrate the need for a naming convention consider the following:

ニコラス・ギャラガーは最近、この問題に対する彼の解決策について書いている。命名規則の必要性を説明するために、次のことを考えてみよう:

/* A component */
.button-group { }

/* A component modifier (modifying .button) */
.button-primary { }

/* A component sub-object (lives within .button) */
.button-icon { }

/* Is this a component class or a layout class? */
.header { }

From looking at the above classes, it’s impossible to tell what type of rule they apply to. This not only increases confusion during development, but it also makes it harder to test your CSS and HTML in an automated way. A structured naming convention allows you to look at a class name and know exactly what its relationship is to other classes and where it should appear in the HTML — making naming easier and testing possible where it previously was not.

上記のクラスを見ただけでは、どのようなルールに適用されるのかがわかりません。これは開発中の混乱を招くだけでなく、CSSやHTMLを自動でテストすることも難しくします。構造化された命名規則によって、クラス名を見て、他のクラスとの関係やHTMLのどこに表示されるべきかを正確に知ることができます。

# Templates Rules (using Sass placeholders)
%template-name { }
%template-name--modifier-name { }
%template-name__sub-object { }
%template-name__sub-object--modifier-name { }

# Component Rules
.component-name { }
.component-name--modifier-name { }
.component-name__sub-object { }
.component-name__sub-object--modifier-name { }

# Layout Rules
.l-layout-method { }
.grid { }

# State Rules
.is-state-type { }

# Non-styled JavaScript Hooks
.js-action-name { }

The first example redone:

最初の例はやり直した:

/* A component */
.button-group { }

/* A component modifier (modifying .button) */
.button--primary { }

/* A component sub-object (lives within .button) */
.button__icon { }

/* A layout class */
.l-header { }
つきやまつきやま

Tools

Maintaining an effective and well-organized CSS architecture can be very difficult, especially on large teams. A few bad rules here and there can snowball into an unmanageable mess. Once your application’s CSS has entered into the realm of specificity wars and !important trumps, it can be next to impossible to recover without starting over. The key is to avoid those problems from the beginning.

ツール

効果的でよく整理されたCSSアーキテクチャを維持することは、特に大規模なチームでは非常に難しい。あちこちに間違ったルールがあると、雪だるま式に増えて手に負えない混乱に陥ることがあります。ひとたびアプリケーションのCSSが特殊性戦争や!important trumpsの領域に入ってしまうと、最初からやり直さなければ回復するのは不可能に近いでしょう。重要なのは、最初からそのような問題を避けることです。

Fortunately, there are tools that can make controlling your site’s CSS architecture much easier.

幸いなことに、サイトのCSSアーキテクチャーをより簡単にコントロールできるツールがある。

つきやまつきやま

Preprocessors

These days it’s impossible to talk about CSS tools without mentioning preprocessors, so this article won’t be any different. But before I praise their usefulness, I should offer a few words of caution.

プリプロセッサ

最近では、プリプロセッサを抜きにしてCSSツールを語ることはできない。しかし、その有用性を褒め称える前に、いくつか注意すべきことを述べておこう。

Preprocessors help you write CSS faster, not better. Ultimately it gets turned into plain CSS, and the same rules should apply. If a preprocessor lets you write your CSS faster then it also lets you write bad CSS faster, so it’s important to understand good CSS architecture before thinking a preprocessor will solve your problems.

プリプロセッサは、CSSをより速く書くためのものであって、より良く書くためのものではありません。最終的にはプレーンなCSSになり、同じルールが適用されるはずです。プリプロセッサによってCSSをより速く書けるようになるのであれば、悪いCSSもより速く書けるようになります。したがって、プリプロセッサが問題を解決してくれると考える前に、良いCSSアーキテクチャを理解することが重要です。

Many of the so-called “features” of preprocessors can actually be very bad for CSS architecture. The following are some of the “features” I avoid at all costs (and though the general ideas apply to all preprocessor languages, these guidelines apply specifically to Sass).

プリプロセッサのいわゆる「機能」の多くは、実際にはCSSアーキテクチャにとって非常に悪いものです。以下は、私が全力で避けている「機能」の一部です(一般的な考え方はすべてのプリプロセッサ言語に当てはまりますが、これらのガイドラインは特にSassに当てはまります)。

  • Never nest rules purely for code organization. Only nest when the outputted CSS is what you want.
  • Never use a mixin if you’re not passing an argument. Mixins without arguments are much better used as templates which can be extended.
  • Never use @extend on a selector that isn’t a single class. It doesn’t make sense from a design perspective and it bloats the compiled CSS.
  • Never use @extend for UI components in component modifier rules because you lose the inheritance chain (more on this in a bit).
  • 純粋にコードを整理するためだけにルールをネストしてはならない。出力されるCSSが望むものである場合にのみネストすること。
  • 引数を渡さない場合は、決してミキシンを使用しないでください。引数のないmixinは、拡張可能なテンプレートとして使うほうがずっとよい。
  • 単一のクラスでないセレクタに@extendを使わないこと。デザインの観点からは意味がありませんし、コンパイルされたCSSが肥大化します。
  • コンポーネント修飾ルールの中で、UIコンポーネントに@extendを使ってはいけません。

The best parts of preprocessors are functions like @extend and %placeholder. Both allow you to easily manage CSS abstraction without adding bloat to your CSS or a huge list of base classes in your HTML that can be very hard to manage.

プリプロセッサの最も優れた点は、@extend%placeholderのような関数です。どちらも、CSSを肥大化させることなく、CSSの抽象化を簡単に管理できるようにします。

@extend should be used with care though because sometime you want those classes in your HTML. For example, when you first learn about @extend it might be tempting to use it with all of your modifier classes like so:

プリプロセッサの最も優れた点は、@extend%placeholderのような関数です。どちらも、CSSを肥大化させることなく、CSSの抽象化を簡単に管理できるようにします。

.button {
  /* button styles */
}

/* Bad */
.button--primary {
  @extend .button;
  /* modification styles */
}

The problem with doing this is you lose the inheritance chain in the HTML. Now it’s very difficult to select all button instances with JavaScript.

この方法の問題点は、HTMLの継承チェーンが失われることだ。JavaScriptですべてのボタン・インスタンスを選択するのは非常に難しくなる。

As a general rule, I never extend UI components or anything that I might want to know the type of later. This is what templates are for and another way to help distinguish between templates and components. A template is something you wouldn’t ever need to target in your application logic, and therefore can be safely extended with a preprocessor.

一般的なルールとして、私はUIコンポーネントや後で種類を知りたくなるようなものを拡張することはない。これがテンプレートであり、テンプレートとコンポーネントを区別するためのもう一つの方法だ。テンプレートは、アプリケーション・ロジックでターゲットにする必要のないもので、プリプロセッサで安全に拡張できます。

Here’s how it might look using the modal example referenced above:

上記で言及したモーダルの例を使用すると、次のようになります:

.modal {
  @extend %dialog;
  @extend %drop-shadow;
  @extend %statically-centered;
  /* other modal styles */
}

.modal__close {
  @extend %dialog__close;
  /* other close button styles */
}

.modal__header {
  @extend %background-gradient;
  /* other modal header styles */
}