blob: a2b48cf37a35dfa5bd19197407ee3e0721090db8 [file] [log] [blame] [view]
Andrew Bonventrecf2a3162019-03-22 16:18:58 -04001# Go CSS Coding Guidelines
2
3**Please [discuss changes](https://golang.org/issue/new?title=wiki%3A+CSSStyleGuide+change&body=&labels=Documentation) before editing this page**, even _minor_ ones. Many people have opinions and this is not the place for edit wars.
4
5Go's naming conventions are adapted from [Medium's style guide](https://gist.github.com/fat/a47b882eb5f84293c4ed#javascript) and the work being done in the [SUIT CSS framework](https://github.com/suitcss/suit/blob/master/doc/naming-conventions.md). Which is to say, it relies on _structured class names_ and _meaningful hyphens_ (i.e., not using hyphens merely to separate words). This is to help work around the current limits of applying CSS to the DOM (i.e., the lack of style encapsulation) and to better communicate the relationships between classes.
6
7We require plain CSS over preprocessors like LESS, SASS, etc. This is to avoid additional tooling dependencies.
8
9## JavaScript
10
11syntax: `js-<targetName>`
12
13JavaScript-specific classes reduce the risk that changing the structure or theme of components will inadvertently affect any required JavaScript behavior and complex functionality. You must use these classes if you interact with the DOM via JavaScript. In practice this looks like this:
14
15```
16<a href="/login" class="btn btn-primary js-login"></a>
17```
18
19Again, JavaScript-specific classes should not, under any circumstances, be styled.
20
21## Components
22
23Syntax: `[namespace-]<ComponentName>[-descendantName][--modifierName]`
24
25Component driven development offers several benefits when reading and writing HTML and CSS:
26
27* It helps to distinguish between the classes for the root of the component, descendant elements, and modifications.
28* It keeps the specificity of selectors low.
29* It helps to decouple presentation semantics from document semantics.
30
31You can think of components as custom elements that enclose specific semantics, styling, and behavior.
32
33### namespace (optional)
34
35If necessary, components can be prefixed with a namespace. For example, you may wish to avoid the potential for collisions between libraries and your custom components by prefixing all your components with a namespace.
36
37```
38.godoc-Button { /* … */ }
39.godoc-Tabs { /* … */ }
40```
41
42This makes it clear, when reading the HTML, which components are part of your library.
43
44### ComponentName
45
46The component's name must be written in camel case.
47
48```
49.MyComponent { /* … */ }
50<article class="MyComponent">
51
52</article>
53```
54
55### ComponentName--modifierName
56
57A component modifier is a class that modifies the presentation of the base component in some form. Modifier names must be written in camel case and be separated from the component name by two hyphens. The class should be included in the HTML _in addition_ to the base component class.
58
59```
60/* Core button */
61.Button { /* … */ }
62/* Default button style */
63.Button--default { /* … */ }
64<button class="Button Button--primary">…</button>
65```
66
67### ComponentName-descendantName
68
69A component descendant is a class that is attached to a descendant node of a component. It's responsible for applying presentation directly to the descendant on behalf of a particular component. Descendant names must be written in camel case.
70
71```
72<article class="Tweet">
73 <header class="Tweet-header">
74 <img class="Tweet-avatar" src="{$src}" alt="{$alt}">
75
76 </header>
77 <div class="Tweet-body">
78
79 </div>
80</article>
81```
82
83### ComponentName[aria-<state of component>]
84
85Almost always, component states can be represented using ARIA (aria-expanded, aria-disabled, etc.) so they are recommended for state-based modifications of components. In the very rare case that there is a state that cannot be represented using ARIA, a CSS class of the format `is-stateName` can be used. The CSS state name must be Camel case. Never style these attributes/classes directly; they should always be used as an adjoining class or attribute.
86
87JS can add/remove these attributes/classes. Every component must define its own styles for the state (as they are scoped to the component).
88
89```
90.Tweet { /* … */ }
91.Tweet[aria-expanded=true] { /* … */ }
92.Tweet.is-Blorked { /* … */ }
93<article class="Tweet is-Blorked" aria-expanded="true">
94
95</article>
96```
97
98### Colors
99
100Prefer lower-case hex values, RGB, or RGBA over named, HSL, or HSLA values. Use short-form hex values where applicable.
101
102Right:
103
104```
105#fff;
106#f1f2f3;
107rgb(50, 50, 50);
108rgba(50, 50, 50, 0.2);
109```
110
111Wrong:
112
113```
114#FFFFFF;
115#F1F2F3;
116white;
117hsl(120, 100%, 50%);
118hsla(120, 100%, 50%, 1);
119```
120
121## Formatting
122
123The following are some high level page formatting style rules.
124
125### Spacing
126
127CSS rules should be comma separated but live on new lines:
128
129Right:
130
131```
132.Content,
133.Content-edit {
134
135}
136```
137
138Wrong:
139
140```
141.Content, .Content-edit {
142
143}
144```
145
146CSS blocks should be separated by a single new line. not two. not 0.
147
148Right:
149
150```
151.Content {
152
153}
154.Content-edit {
155
156}
157```
158
159Wrong:
160
161```
162.Content {
163
164}
165
166.Content-edit {
167
168}
169```
170
171### Quotes
172
173Quotes are optional in CSS. We use single quotes as it is visually clearer that the string is not a selector or a style property.
174
175Right:
176
177```
178background-image: url('/img/you.jpg');
179font-family: 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial;
180```
181
182
183Wrong:
184
185```
186background-image: url(/img/you.jpg);
187font-family: Helvetica Neue Light, Helvetica Neue, Helvetica, Arial;
188```
189
190## Write Simple Selectors
191
192Avoid sequences of simple selectors ("compound selectors").
193
194The only exceptions are state-based selectors that are dynamically added to indicate a state change (for example, a tweet that has "[aria-expanded=true]").
195
196Right:
197
198```
199/* State-based simple selector. */
200tweet[aria-expanded=true] {
201 ...
202}
203```
204
205Wrong:
206
207```
208/* Sequence of simple selectors. */
209button.foo.bar {
210 ...
211}