├── .github
└── PULL_REQUEST_TEMPLATE.md
├── .scss-lint.yml
├── Gemfile
├── README.md
└── _example.scss
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## What?
2 | ...
3 |
4 | ## Why?
5 | ...
6 |
7 | ## Testing / Proof
8 | ...
9 |
10 | @bigcommerce/frontend
11 |
--------------------------------------------------------------------------------
/.scss-lint.yml:
--------------------------------------------------------------------------------
1 | # BC configuration
2 | linters:
3 |
4 | #Cos we use maps with keywords, this produces noise
5 | ColorKeyword:
6 | enabled: false
7 |
8 | ElsePlacement:
9 | enabled: true
10 | style: new_line # or 'same_line'
11 |
12 | EmptyLineBetweenBlocks:
13 | enabled: true
14 | ignore_single_line_blocks: false
15 |
16 | Indentation:
17 | enabled: true
18 | character: space # or 'tab'
19 | width: 4
20 |
21 | LeadingZero:
22 | enabled: true
23 | style: include_zero # or 'exclude_zero'
24 |
25 | NameFormat:
26 | enabled: false
27 | convention: hyphenated_lowercase # or 'BEM', or a regex pattern
28 |
29 | SelectorDepth:
30 | enabled: true
31 | max_depth: 2
32 |
33 | NestingDepth:
34 | enabled: true
35 | max_depth: 2
36 |
37 | # For example
38 | # http://www.regexr.com/39qql
39 | SelectorFormat:
40 | enabled: true
41 | # convention: camel_case # or 'snake_case', or 'hyphenated_lowercase', or a regex pattern
42 | convention: ^[a-z][a-z0-9]*([A-Z0-9][a-z0-9]*)*((\.is-|-+)[a-z0-9][a-z0-9]*([A-Z0-9][a-z0-9]*)*)*$
43 |
44 | StringQuotes:
45 | enabled: true
46 | style: double_quotes # or single_quotes
47 |
48 | TrailingZero:
49 | enabled: true
50 |
51 | # This is a new linting rule as of 0.30 and the per-file disablement syntax seems to failing, so turn it off
52 | QualifyingElement:
53 | enabled: false
54 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'sass', '3.4.7'
4 | gem 'scss-lint', '~> 0.31.0'
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Sass Coding Guidelines
2 |
3 | Bigcommerce uses [Sass](http://sass-lang.com/) for style generation.
4 |
5 | Bigcommerce's naming conventions are heavily influenced by the SUIT CSS framework
6 | and align closely to [Medium](https://medium.com/@fat/mediums-css-is-actually-pretty-fucking-good-b8e2a6c78b06)'s
7 | thoughts on CSS. Which is to say, it relies on _structured class names_ and
8 | _meaningful hyphens_ (i.e., not using hyphens merely to separate words). This
9 | helps to work around the current limits of applying CSS to the DOM (i.e., the
10 | lack of style encapsulation), and to better communicate the relationships between
11 | classes.
12 |
13 |
14 | **Table of contents**
15 |
16 | * [General Principles](#principles)
17 | * [Specificity](#specificity)
18 | * [Performance](#performance)
19 | * [Formatting](#formatting)
20 | * [Indentation](#indentation)
21 | * [Commenting](#commenting)
22 | * [Spacing](#spacing)
23 | * [Quotes](#quotes)
24 | * [Value Declaration](#value-declaration)
25 | * [Declaration Order](#declaration-order)
26 | * [Pseudo Elements and Classes](#pseudo)
27 | * [Units](#units)
28 | * [Nesting](#nesting)
29 | * [@extend or @inlcude](#extendorinclude)
30 | * [Components](#components)
31 | * [componentName](#componentName)
32 | * [componentName--modifierName](#componentName--modifierName)
33 | * [componentName-descendantName](#componentName-descendantName)
34 | * [componentName.is-stateOfComponent](#is-stateOfComponent)
35 | * [Utilities](#utilities)
36 | * [u-utilityName](#u-utilityName)
37 | * [Variables and Mixins](#variables-and-mixins)
38 | * [Variables](#variables)
39 | * [Component / Micro app variables](#component-variables)
40 | * [Maps](#variable-maps)
41 | * [colors](#colors)
42 | * [z-index](#zindex)
43 | * [font-weight](#fontweight)
44 | * [line-height](#lineheight)
45 | * [Animations](#animations)
46 | * [Mixins](#mixins)
47 | * [Polyfills](#polyfills)
48 | * [JavaScript](#javascript)
49 | * [Folder Structure](#folders)
50 |
51 |
52 |
53 |
54 | ## General Principles
55 | Strictly adhere to the agreed-upon style guide listed below. The general
56 | principle is to develop DRY (Don't Repeat Yourself) SCSS, built around reusable
57 | components and patterns.
58 |
59 | * All code should look like a single person has typed it.
60 | * Don't try to prematurely optimize your code; keep it readable and understandable.
61 | * When building a component, always start by looking at existing patterns.
62 | * Break down complex components until they are made up of simple components.
63 | * Save your complex components as patterns so they can be easily reused.
64 | * Build your component as a mixin which outputs _optional_ css.
65 |
66 |
67 |
68 | ## Specificity
69 |
70 | On large code bases, it's preferable and a tonne more maintainable if the
71 | specificity of selectors are all as equal and as low as humanly possible.
72 |
73 |
74 | > **Do:**
75 | > Use classes in your SCSS for styling.
76 |
77 | ```css
78 | .component {
79 | ...
80 | }
81 | ```
82 |
83 |
84 | > **Don't:**
85 | > Use ID's for styling. There is literally no point in using them.
86 |
87 | ```css
88 | #component {
89 | ...
90 | }
91 | ```
92 |
93 |
94 | > **Do:**
95 | > Style the base elements (such as typography elements).
96 |
97 | ```css
98 | h1 {
99 | ...
100 | }
101 | ```
102 |
103 | > **Don't:**
104 | > Reference or style descendent elements in your class selectors.
105 |
106 | ```css
107 | .component h1 {
108 | ...
109 | }
110 | ```
111 |
112 |
113 | > **Don't:**
114 | > Use overqualified selectors in your CSS. Do not prepend a class or ID with an element.
115 |
116 | ```css
117 | div.container {
118 | ...
119 | }
120 | ```
121 |
122 |
123 | #### Performance
124 | Overly specific selectors can also cause performance issues. Consider:
125 |
126 | ```css
127 | ul.user-list li span a:hover {
128 | color: red;
129 | }
130 | ```
131 |
132 | Selectors are resolved right to left, exiting when it has been detected the
133 | selector does not match. This requires a lot of DOM walking and for large
134 | documents can cause a significant increase in the layout time. For further
135 | reading checkout: https://developers.google.com/speed/docs/best-practices/rendering#UseEfficientCSSSelectors
136 |
137 | If we know we want to give all `a` elements inside the `.user-list` red on
138 | hover we can simplify this style to:
139 |
140 | ```css
141 | .user-list-link:hover {
142 | color: red;
143 | }
144 | ```
145 |
146 |
147 |
148 | ## Formatting
149 |
150 | The following are some high level page formatting style rules.
151 |
152 | * Remove all trailing white-space from your file, Sublime Text can even do this upon saving.
153 | * Tip: set your editor to show white-space.
154 | * Leave one clear line at the bottom of your file.
155 |
156 |
157 | #### Indentation
158 |
159 | * Don't mix spaces with tabs for indentation.
160 | * Use a soft-tab of 4 spaces.
161 | * Use white-space to improve readability.
162 | * Feel free to use indentation to show hierarchy.
163 |
164 | > **Do:**
165 |
166 | ```css
167 | .component {
168 | ...
169 | }
170 |
171 | .component-child {
172 | ...
173 | }
174 |
175 | .component-childSecond {
176 | ...
177 | }
178 | ```
179 |
180 |
181 | #### Commenting
182 | * Separate your code into logical sections using standard comment blocks.
183 | * Leave one clear line under your section comments.
184 | * Leave two clear lines above comment blocks.
185 | * Annotate your code inside a comment block, leaving a reference # next to the line.
186 |
187 | > **Do:**
188 | > Comment your code
189 | > No really, comment your code
190 |
191 | ```css
192 | // =============================================================================
193 | // FILE TITLE / SECTION TITLE
194 | // =============================================================================
195 |
196 |
197 | // Comment Block / Sub-section
198 | // -----------------------------------------------------------------------------
199 | //
200 | // Purpose: This will describe when this component should be used. This comment
201 | // block is 80 chars long
202 | //
203 | // 1. Mark lines of code with numbers which are explained here.
204 | // This keeps your code clean, while also allowing detailed comments.
205 | //
206 | // -----------------------------------------------------------------------------
207 |
208 | .component {
209 | ... // 1
210 | }
211 |
212 | ```
213 |
214 |
215 | #### Spacing
216 |
217 | * CSS rules should be comma separated but live on new lines.
218 | * Include a single space before the opening brace of a rule-set.
219 | * Include a single space after the colon of a declaration.
220 | * Include a semi-colon at the end of every declaration in a declaration block.
221 | * Include a space after each comma in comma-separated property or function values.
222 | * Place the closing brace of a rule-set on its own line.
223 | * CSS blocks should be separated by a single clear line.
224 | * Add two blank lines between sections and one between sub-sections.
225 |
226 | > **Do:**
227 |
228 | ```css
229 | .content,
230 | .content-edit {
231 | padding: 0;
232 | margin: 0;
233 | font-family: "Helvetica", sans-serif;
234 | }
235 |
236 |
237 | .newSection {
238 | ...
239 | }
240 |
241 | .newSection-edit {
242 | ...
243 | }
244 | ```
245 |
246 | > **Don't:**
247 |
248 | ```css
249 | .content, .content-edit{
250 | padding:0; margin:0;
251 | font-family: "Helvetica",sans-serif}
252 | .newSection {
253 | ...
254 | }
255 | .newSection-edit {
256 | ...
257 | }
258 | ```
259 |
260 |
261 | #### Quotes
262 |
263 | > **Do:**
264 | > Always use double quotes when available.
265 | > Quote attribute values in selectors
266 |
267 | ```css
268 | input[type="checkbox"] {
269 | background-image: url("/img/you.jpg");
270 | font-family: "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial;
271 | }
272 | ```
273 |
274 | > **Don't:**
275 |
276 | ```css
277 | input[type=checkbox] {
278 | background-image: url(/img/you.jpg);
279 | font-family: Helvetica Neue Light, Helvetica Neue, Helvetica, Arial;
280 | }
281 | ```
282 |
283 |
284 | #### When declaring values
285 | * Use lower-case and shorthand hex values
286 | * Use unit-less line-height values
287 | * Where allowed, avoid specifying units for zero values
288 | * Never specify the height property unless it's specifically needed (`min-height` is cool)
289 | * Never use `!important` (Utility classes are an exception but still should be
290 | avoided)
291 | * Try to only style the property you are explicitly concerned with to reduce
292 | over zealously resetting something you might want to inherit
293 | * `background-color: #333` over `background: #333`
294 | * `margin-top: 10px` over `margin: 10px 0 0`
295 | * Use shorthand if you can, be sensible
296 |
297 | > **Do:**
298 |
299 | ```css
300 | .component {
301 | background-color: #ccc;
302 | color: #aaa;
303 | left: 0;
304 | line-height: 1.25;
305 | min-height: 400px;
306 | padding: 0 20px;
307 | top: 0;
308 | }
309 | ```
310 |
311 | > **Don't:**
312 |
313 | ```css
314 | .component {
315 | background: #ccc;
316 | color: #AAAAAA;
317 | left: 0px;
318 | line-height: 24px;
319 | height: 400px !important; //jerk #yolo FUUUUUU
320 | padding: 0px 20px 0px 20px;
321 | top: 0px;
322 | }
323 | ```
324 |
325 |
326 |
327 | #### Declaration order
328 | There are a millions opinions and thoughts on logical ordering and grouping.
329 | Don't force someone to learn your opinion, ordering doesn't matter, consistency
330 | does. Just use the alphabet, _everyone_ knows it.
331 | * @extend
332 | * @include
333 | * Alphabetical, always.
334 |
335 | > **Do**
336 |
337 | ```css
338 | .component {
339 | @extend %a-placeholder;
340 | @include silly-links;
341 | color: #aaa;
342 | left: 0;
343 | line-height: 1.25;
344 | min-height: 400px;
345 | padding: 0 20px;
346 | top: 0;
347 | width: 150px;
348 | }
349 | ```
350 |
351 | > **Don't:**
352 |
353 | ```css
354 | .component {
355 | min-height: 400px;
356 | left: 0;
357 | @include silly-links;
358 | top: 0;
359 | width: 150px;
360 | color: #aaa;
361 | @extend %a-placeholder;
362 | line-height: 1.25;
363 | width: 200px;
364 | padding: 0 20px;
365 | }
366 | ```
367 |
368 |
369 | ## Pseudo Elements and Classes
370 | Pseudo elements and classes are very different things, as is the syntax used to
371 | declare them. Declare pseudo _**classes**_ with a single colon. Declare pseudo
372 | _**elements**_ with a double colon.
373 |
374 | > **Do**
375 |
376 | ```css
377 | .component:focus {
378 | ...
379 | }
380 |
381 | .component:hover {
382 | ...
383 | }
384 |
385 | .component::before {
386 | ...
387 | }
388 |
389 | .component::after {
390 | ...
391 | }
392 | ```
393 |
394 | > **Don't**
395 |
396 | ```css
397 | .component:after {
398 | ...
399 | }
400 | ```
401 |
402 |
403 |
404 | ## Units
405 |
406 | > **Do:**
407 |
408 | * Use `rem` units as primary unit type. This includes:
409 | * Positioning (`top`, `right`, `bottom`, `left`)
410 | * Dimensions (Such as `width`, `height`, `margin`, `padding`)
411 | * Font size
412 | * Use `px` units as primary unit type for the following properties:
413 | * Border widths (`border: 1px solid #bada55;`)
414 | * Use `%` units only if necessary, where `rem` will not suffice:
415 | * Positioning (`top`, `right`, `bottom`, `left`)
416 | * Dimensions (`width`, `height`)
417 | * Line-height should be kept unit-less. If you find you're using a line-height
418 | with a set unit type, try to think of alternative ways to achieve the same outcome.
419 | If it's a unique case which requires a specific `px` or `rem` unit, outline the
420 | reasoning with comments so that others are aware of its purpose.
421 |
422 | > **Don't:**
423 |
424 | * Avoid all use of magic numbers. Re-think the problem. (`margin-top: 37px;`)
425 |
426 |
427 |
428 |
429 | ## Nesting
430 |
431 | Nesting is handy, _sometimes_, but will quickly conflict with our
432 | [Specificty](#specificity) and [Performance](#performance) guidelines.
433 |
434 | As we follow conventions and thoughts from popular and widely accepted
435 | methodologies such as BEM, SMACSS and SUIT, the use of the Suffix can help immensely though.
436 |
437 | * Just because you can, doesn't mean you should.
438 | * [Parent Selector Suffixes](http://thesassway.com/news/sass-3-3-released#parent-selector-suffixes)
439 | are neat, but not very searchable
440 | * Watch your output, be mindful of [Specificty](#specificity) and
441 | [Performance](#performance)
442 | * Aim for a maximum depth of just 1 nested rule
443 |
444 | > **Do:**
445 |
446 | ```css
447 | .panel-body {
448 | position: relative;
449 | }
450 |
451 | .panel-sideBar {
452 | z-index: 10;
453 | }
454 |
455 | .panel-sideBar-item {
456 | cursor: pointer;
457 | }
458 |
459 | .panel-sideBar-item-label {
460 | color: #AEAEAE;
461 |
462 | &.has-smallFont {
463 | font-size: 13px;
464 | }
465 | }
466 | ```
467 |
468 | At its worst, this produces:
469 | ```css
470 | .panel-sideBar-item-label.has-smallFont {
471 | font-size: 13px;
472 | }
473 | ```
474 |
475 | > **Don't:**
476 |
477 | ```css
478 | .bc-tab-panel {
479 |
480 | .panel-body {
481 | position: relative;
482 | ...
483 |
484 | .panel-side-bar {
485 | z-index: 10;
486 | ...
487 |
488 | .panel-side-item {
489 | cursor: pointer;
490 | ...
491 |
492 | .panel-side-item-label {
493 | color: #AEAEAE;
494 |
495 | &.small-font {
496 | font-size: 13px;
497 | }
498 | }
499 | }
500 | }
501 | }
502 | }
503 | ```
504 |
505 | At it's worst, this produces:
506 | ```css
507 | .bc-tab-panel .panel-body .panel-side-bar .panel-side-item .panel-side-item-label.small-font {
508 | font-size: 13px;
509 | }
510 | ```
511 |
512 |
513 | ## @extend or @include
514 |
515 | * Excessive use of `@include` can cause unnecessary bloat to your stylesheet, but
516 | gzip should help with that.
517 | * Excessive use of `@extend` can create large selector blocks (not helpful in web inspector)
518 | and hoisting of your selector can cause override and inheritance issues.
519 | * We advise to `@include` over `@extend` generally, but use common sense. In situations where it's better to `@extend` it's safer to do so on a placeholder selector.
520 |
521 | > **Do:**
522 | > Make use of placeholder selectors to separate repeated local styles
523 |
524 | ```css
525 | %placeholderSelector {
526 | background-color: #eee;
527 | }
528 |
529 | .component1 {
530 | @extend %placeholderSelector;
531 | color: red;
532 | }
533 |
534 | .component2 {
535 | @extend %placeholderSelector;
536 | color: blue;
537 | }
538 | ```
539 |
540 |
541 | ## Components
542 |
543 | Syntax: `[--modifierName|-descendantName]`
544 |
545 | This component syntax is mainly taken from [Suit CSS](http://suitcss.github.io/)
546 | with minor modifications.
547 |
548 | Component driven development offers several benefits when reading and writing
549 | HTML and CSS:
550 |
551 | * It helps to distinguish between the classes for the root of the component,
552 | descendant elements, and modifications.
553 | * It keeps the specificity of selectors low.
554 | * It helps to decouple presentation semantics from document semantics.
555 |
556 | You can think of components as custom elements that enclose specific semantics,
557 | styling, and behaviour.
558 |
559 | **Do not choose a class name based on its visual presentation or its content.**
560 |
561 | The primary architectural division is between components and utilities:
562 |
563 | * componentName (eg. `.dropdown` or `.buttonGroup`)
564 | * componentName--modifierName (eg. `.dropdown--dropUp` or `.button--primary`)
565 | * componentName-descendantName (eg. `.dropdown-item`)
566 | * componentName.is-stateOfComponent (eg. `.dropdown.is-active`)
567 | * u-utilityName (eg. `.u-textTruncate`)
568 | * `[-][--modifierName|-descendentName]`
569 |
570 |
571 |
572 |
573 | #### ComponentName
574 |
575 | The component's name must be written in camel case. Use class names that are as
576 | short as possible but as long as necessary.
577 |
578 | * Example: `.nav` not `.navigation`
579 | * Example: `.button` not `.btn`
580 |
581 | ```css
582 | .myComponent { /* ... */ }
583 | ```
584 |
585 | ```html
586 |
587 | ...
588 |
589 | ```
590 |
591 |
592 | #### componentName--modifierName
593 |
594 | A component modifier is a class that modifies the presentation of the base
595 | component in some form. Modifier names must be written in camel case and be
596 | separated from the component name by two hyphens. The class should be included
597 | in the HTML _in addition_ to the base component class.
598 |
599 | ```css
600 | /* Core button */
601 | .button {
602 | ...
603 | }
604 |
605 | .button--primary {
606 | ...
607 | }
608 | ```
609 |
610 | ```html
611 |
612 | ```
613 |
614 | #### componentName-descendantName
615 |
616 | A component descendant is a class that is attached to a descendant node of a
617 | component. It's responsible for applying presentation directly to the descendant
618 | on behalf of a particular component. Descendant names must be written in camel case.
619 |
620 | ```html
621 |
622 |
623 |
624 | ...
625 |
626 |
627 | ...
628 |
629 |
630 | ```
631 |
632 | You might notice that `tweet-avatar`, despite being a descendant of `tweet-header`
633 | does not have the class of `tweet-header-avatar`. Why? Because it doesn't necessarily
634 | **have** to live there. It could be adjacent to `tweet-header` and function the same
635 | way. Therefore, you should **only** prepend a descendant with its parent if must
636 | live there. Strive to keep class names as short as possible, but as long as necessary.
637 |
638 | When building a component, you'll often run into the situation where you have a
639 | list, group or simply require a container for some descendants. In this case, it's
640 | much better to follow a pattern of pluralising the container and having each
641 | descendant be singular. This keeps the relationship clear between descendant levels.
642 |
643 | > **Do:**
644 |
645 | ```html
646 |
653 | ```
654 |
655 | ```html
656 |
682 | ```
683 |
684 |
685 | #### componentName.is-stateOfComponent
686 |
687 | Use `is-stateName` for state-based modifications of components. The state name
688 | must be Camel case. **Never style these classes directly; they should always be
689 | used as an adjoining class.**
690 |
691 | JS can add/remove these classes. This means that the same state names can be used
692 | in multiple contexts, but every component must define its own styles for the state
693 | (as they are scoped to the component).
694 |
695 | ```html
696 |
697 | ...
698 |
699 | ```
700 |
701 | ```css
702 | .tweet {
703 | ...
704 | }
705 |
706 | .tweet.is-expanded {
707 | ...
708 | }
709 | ```
710 |
711 |
712 | ## Utilities
713 |
714 | Utility classes are low-level structural and positional traits. Utilities can
715 | be applied directly to any element; multiple utilities can be used together;
716 | and utilities can be used alongside component classes.
717 |
718 | Utility classes should be used sparingly, lean towards component level styling
719 | to make for as reusable HTML patterns as possible.
720 |
721 |
722 |
723 | #### u-utilityName
724 |
725 | Syntax: `u-`
726 |
727 | Utilities must use a camel case name, prefixed with a `u` namespace.
728 |
729 |
730 |
731 | ## Variables and Mixins
732 |
733 | Variables and Mixins should follow similar naming conventions.
734 |
735 |
736 | #### Variables
737 |
738 | Syntax: `[[--modifierName][-descendentName]-]-[--]`
739 |
740 | Variables should be named as such, things that can change over time.
741 |
742 | Variables should also follow our component naming convention to show context
743 | and be in camelCase. If the variable is a global, generic variable, the property
744 | name should be prefixed first, followed by the variant and or modifier name for
745 | clearer understanding of use.
746 |
747 | > **Do:**
748 | > Abstract your variable names
749 |
750 | ```CSS
751 | $color-brandPrimary: #aaa;
752 | $fontSize: 1rem;
753 | $fontSize--large: 2rem;
754 | $lineHeight--small: 1.2;
755 | ```
756 |
757 | > **Don't:**
758 | > Name your variables after the color value
759 |
760 | ```css
761 | $bigcommerceBlue: #00abc9;
762 | $color-blue: #00ffee;
763 | $color-lightBlue: #eeff00;
764 | ```
765 |
766 |
767 | #### Component / Micro App level variables
768 |
769 | Micro apps must base their local variables on the global variables primarily.
770 | You may add your own specific variables as required if no global variable is available.
771 |
772 | For portability, your component should declare it's own set of variables inside
773 | it's own settings partial, inside the settings folder. Even if at the time, your
774 | component only uses globally available variables from Bigcommerce's Library,
775 | you should reassign the global variable to a local one.
776 | If your component styles change from those global variables at all in the future,
777 | less of your SCSS will have to change, as you only change the local variable value.
778 |
779 | If your variable is scoped to your component, it should be namespaced as such following
780 | our component naming conventions.
781 |
782 | > **Do:**
783 |
784 | ```css
785 | $componentName-fontSize: fontSize("small");
786 | $componentName-decendantName-backgroundColor: #ccc;
787 | $componentName-decendantName-marginBottom: fontSize("large");
788 | $componentName-decendantName--active-backgroundColor: #000;
789 | ```
790 |
791 | ```css
792 | .componentName {
793 | font-size: $componentName-fontSize;
794 | }
795 |
796 | .componentName-decendantName {
797 | background-color: $componentName-decendantName-backgroundColor;
798 | margin-bottom: $componentName-decendantName-marginBottom;
799 | }
800 |
801 | .componentName-decendantName--active {
802 | background-color: $componentName-decendantName--active-backgroundColor;
803 | }
804 | ```
805 |
806 |
807 | #### Maps, maps are cool
808 |
809 | Variable maps with a simple getter mixin, can help simplify your variable names
810 | when calling them, and help better group variables together using their
811 | relationship. [More info](http://erskinedesign.com/blog/friendlier-colour-names-sass-maps/)
812 |
813 | > **Do:**
814 |
815 | ```scss
816 | // Setting variables and mixin
817 | // -----------------------------------------------------------------------------
818 |
819 | $colors: (
820 | primary: (
821 | base: #00abc9,
822 | light: #daf1f6,
823 | dark: #12799a
824 | ),
825 | secondary: (
826 | base: #424d55,
827 | light: #ccc,
828 | lightest: #efefef,
829 | dark: #404247
830 | ),
831 | success: (
832 | base: #bbd33e,
833 | light: #eaf0c6
834 | )
835 | );
836 |
837 | @function color($color, $tone: "base") {
838 | @return map-get(map-get($colors, $color), $tone);
839 | }
840 | ```
841 |
842 |
843 | ```scss
844 | // Usage
845 | // -----------------------------------------------------------------------------
846 |
847 | body {
848 | color: color("secondary");
849 | }
850 |
851 | h1,
852 | h2,
853 | h3 {
854 | color: color("secondary", "dark");
855 | }
856 |
857 | .alert {
858 | background-color: color("primary", "light");
859 | }
860 |
861 | .alert-close {
862 | color: color("primary");
863 | }
864 |
865 | .alert--success {
866 | background-color: color("success", "light");
867 |
868 | > .alert-close {
869 | color: color("success");
870 | }
871 | }
872 | ```
873 |
874 | **Every variable used in the core architecture must be based off the global
875 | variables.**
876 |
877 |
878 | #### Colors
879 |
880 | Please only use the globally available colors from the Bigcommerce Library.
881 | Your Micro app or component shouldn't really have a need for a *new* color.
882 | This creates consistency and sanity.
883 |
884 | Avoid using the `darken(color, %)` and `lighten(color, %)` mixins for similar reasons.
885 |
886 | Use the color maps available to you:
887 | ```css
888 | .component {
889 | background-color: color("brand", "primary");
890 | }
891 | ```
892 |
893 |
894 | #### z-index scale
895 |
896 | Please use the z-index scale defined in the Bigcommerce Library under global settings.
897 |
898 | `zIndex("lowest")` or `zIndex("high")` for example.
899 |
900 |
901 |
902 | #### Font Weight
903 |
904 | Bigcommerce apps share a strict set of font weights. Never declare a new font weight,
905 | only use the available font settings from the Bigcommerce Library. e.g.
906 |
907 | ```css
908 | fontWeight("light");
909 | fontWeight("semibold");
910 | ```
911 |
912 |
913 |
914 | #### Line Height
915 |
916 | The Bigcommerce Library also provides a line height scale. This should be used for blocks
917 | of text. e.g.
918 |
919 | ```css
920 | lineHeight("smallest");
921 | lineHeight("large");
922 | ```
923 |
924 | Alternatively, when using line height to vertically centre a single line of text,
925 | be sure to set the line height to the height of the container - 1.
926 |
927 | ```CSS
928 | .button {
929 | height: remCalc(50px);
930 | line-height: remCalc(49px);
931 | }
932 | ```
933 |
934 |
935 | #### Animations
936 |
937 | Animation delays, durations and easing should be taken from the global framework
938 |
939 |
940 | #### Mixins
941 |
942 | Mixins follow regular camel case naming conventions and do not require namespacing. If you are creating a mixin for a utility, it will need to match the utility name (including `u` namespacing).
943 |
944 | * `@mixin buttonVariant;`
945 | * `@mixin u-textTruncate;`
946 |
947 |
948 | ## Polyfills
949 |
950 | At Bigcommerce, we try not to replicate CSS polyfills that auto-prefixer can
951 | supply in a Grunt or Gulp task. This keeps our SCSS code base lean and future proof.
952 |
953 | > **Do:**
954 |
955 | ```css
956 | .button {
957 | border-radius: 3px;
958 | }
959 | ```
960 |
961 | > **Don't:**
962 | > Add vendor prefixes at all.
963 |
964 | ```css
965 | .button {
966 | @include border-radius(3px);
967 | }
968 | ```
969 | ```css
970 | .button {
971 | -ms-border-radius: 3px;
972 | -o-border-radius: 3px;
973 | -webkit-border-radius: 3px;
974 | border-radius: 3px;
975 | }
976 | ```
977 |
978 |
979 | ## JavaScript
980 |
981 | syntax: `js-`
982 |
983 | JavaScript-specific classes reduce the risk that changing the structure or theme
984 | of components will inadvertently affect any required JavaScript behaviour and
985 | complex functionality. It is not necessary to use them in every case, just
986 | think of them as a tool in your utility belt. If you are creating a class, which
987 | you don't intend to use for styling, but instead only as a selector in JavaScript,
988 | you should probably be adding the `js-` prefix. In practice this looks like this:
989 |
990 | ```html
991 |
992 | ```
993 |
994 | **Again, JavaScript-specific classes should not, under any circumstances, be styled.**
995 |
996 |
997 | ## Folder Structure
998 |
999 | #### General principle
1000 | The Sass folder structure we're proposing, will have two slight differences
1001 | between the core framework and micro apps, however the bulk of the structure is
1002 | identical between the two.
1003 |
1004 | The idea is to have the least amount of folders as possible, but as many as we
1005 | need to define clear, structured patterns in your Sass.
1006 |
1007 | #### Core Folder Structure
1008 |
1009 | ```
1010 | .
1011 | ├── sass
1012 | | ├── settings/
1013 | | └── tools/
1014 | | └── vendor/
1015 | | └── components/
1016 | | └── utilities/
1017 | ```
1018 |
1019 |
1020 | **/settings:** Contains all of your SCSS variables for your framework. Within
1021 | this folder is 1 primary file `_settings.scss`, which imports all other variable
1022 | files that have been broken into logical files such as `_colors.scss`,
1023 | `_typography.scss`, `_z-index.scss` and your chosen frameworks variables, for
1024 | example `_foundation.scss`.
1025 |
1026 | **/tools:** Contains all of your Sass mixins. Within this folder is 1 primary
1027 | file `_tools.scss`, which imports all other mixin files that have been broken into
1028 | logical files. No framework mixins should appear in this folder as they can be
1029 | consumed from their own respective `/vendor` or `/components` folder.
1030 |
1031 | **/vendor:** Contains all of your vendor files, such as normalize, bootstrap,
1032 | foundation, animate.css, etc. All readily consumable third party files belong
1033 | here, and can be imported in the framework base file as required. No file in
1034 | the /vendor folder should ever be modified.
1035 |
1036 | **/components:** Contains all of your components. This folder will make up the
1037 | vast majority of your compiled CSS. All custom components simply live inside
1038 | this folder, for example `/components/component/_component.scss`. It also contains
1039 | the consumed version of your chosen /vendor framework's components, which will be
1040 | reworked to adhere to the Naming Conventions and Style Guide. They will live
1041 | inside a subfolder of the framework's name, for example `/components/foundation/`.
1042 |
1043 | **/utilities:** Contains all CSS snippets which can be applied to your HTML for
1044 | quick prototyping, or a case by case basis where a unique, yet repeatable style
1045 | is required. Every utility found within this folder will have both a class and a
1046 | mixin. An example being, truncatedText. You can utilise it by applying the class
1047 | `.u-truncatedText` or by applying a mixin, `@include truncatedText;`.
1048 |
1049 |
1050 | #### Micro App Folder Structure
1051 |
1052 | ```
1053 | .
1054 | ├── sass
1055 | | ├── settings/
1056 | | └── tools/
1057 | | └── vendor/
1058 | | └── layouts/
1059 | | └── components/
1060 | | └── utilities/
1061 | | └── shame/
1062 | ```
1063 |
1064 | There are only two minor differences in a micro app, when compared to the core
1065 | framework. Firstly you'll notice that the /framework folder has been replaced by
1066 | a /layouts folder, as well as the addition of the /shame folder.
1067 |
1068 | **/layouts:** Contains your micro app "layouts" and page specific styling.
1069 | Essentially creating the wrapping sections and grids for your app, where the
1070 | core framework's components will live inside. For example, a layout file could
1071 | potentially be your micro app's navigation. It is important to note that the
1072 | styling for individual navigation items and all other inner components styling
1073 | do not live in the layout file. There purpose is purely for the containing
1074 | elements that set up your app.
1075 |
1076 | **/shame:** This interestingly named folder has one goal: to remain empty. It's
1077 | purpose is the place for all of those hot fixes or quick hacks in throwing
1078 | something together. Any code which you don't feel is "complete" can also live
1079 | here. It creates clear visibility on less than perfect code, especially when it
1080 | comes to code reviews, and creates a trail for your dodgy code that if left
1081 | somewhere in your component/layout code could be forgotten about and left.
1082 |
1083 | **A note on: /components & /utilities:** Within your micro app, these folders should
1084 | only house your app's unique code. Any repeatable component or utility that could
1085 | be re-used across other micro apps should be flagged and a PR opened for adding
1086 | it into the core framework.
1087 |
--------------------------------------------------------------------------------
/_example.scss:
--------------------------------------------------------------------------------
1 | // =============================================================================
2 | // FILE TITLE
3 | // =============================================================================
4 |
5 |
6 | // Comment Block
7 | // -----------------------------------------------------------------------------
8 | //
9 | // Purpose: This will describe when this component should be used. This comment
10 | // block is 80 chars long
11 | //
12 | // -----------------------------------------------------------------------------
13 |
14 |
15 | .component {
16 | @extend %component;
17 | color: #aaa;
18 | left: 0;
19 | line-height: 1.25;
20 | min-height: 40rem;
21 | padding: 0 2rem;
22 | top: 0;
23 | }
24 |
25 | .component-child {
26 | margin: 0;
27 | }
28 |
29 | .component-childSecond {
30 | padding-left: 2rem;
31 | }
32 |
33 |
34 | // Component Sub-Section (Purpose: Describes why this section exists)
35 | // -----------------------------------------------------------------------------
36 |
37 | .componentPart {
38 | color: #333;
39 | }
40 |
41 | .componentPart--modifier {
42 | border: 0;
43 | }
44 |
45 | .componentPart-child {
46 | color: #fff;
47 | }
48 |
--------------------------------------------------------------------------------