Organizacja styli CSS i skryptów JS
I’m sure I’ve said it before but the hardest thing about scaling a website is the CSS. JavaScript is easy, but with CSS you pay for your sins — once you’ve started a mess, it’s not easy to back out of.
Przydatne linki
Narzędzia i automatyzacja
Guidelines - wytyczne
- CSS / Sass
- JavaScript
- Airbnb JavaScript Style Guide
- Node.js Style Guide
editorconfig, JSHint, pisanie kodu JS etc.
- JSHint
- ESLint
Architectures - architektury
BEM - Block, Element, Modifier
Bardzo ważnym jest aby bloki były od siebie niezależne nawet do tego stopnia, że swobodnie można zagnieżdżać jeden w drugim lub wyciągać jeden zagnieżdżony w innym bloku i przenieść w zupełnie inne miejsce strony.
Zasady CSS:
- Każdemu blokowi i/lub elementowi musimy nadać unikalną nazwę (w tym wypadku chodzi o klasę CSS), np.
contact
,contact__input
lubcontact__input--important
- Nie używamy selektorów elementu HTML, jak np.
div
,input
- Nie używamy selektorów id, jak np,
#contact-form
- Wystrzegamy się stosowania selektorów opartych o zasadę kaskadowości (selektory potomka), jak np.
.contact__input label
, lepiej np..contact__input-label
lub.contact__label
- Źródło: Block, Element, Modifier w CSS
Organizacja styli
Struktura folderów
The 7-1 Pattern
base/
– contains global styles, such as resets, typography, colors, etc.components/
– contains each self-contained component in its own.scss
partiallayout/
– contains styling for larger layout components; e.g. nav, header, footer, etc.pages/
– contains page-specific styling, if necessarythemes/
– contains styling for different themesutils/
– contains global mixins, functions, helper selectors, etc.vendors/
– contains 3rd-party styles, mixins, etc.main.scss
– output file that brings together all of the above parts
Each folder should have a single .scss
partial file that collects the other files in the same directory – such as _module.scss
(my preference) or _glob.scss
. Then, you can reference each of these in the main.scss
file:
// main.scss
@import 'base/module';
@import 'components/module';
@import 'layout/module';
@import 'pages/module';
@import 'themes/module';
@import 'utils/module';
@import 'vendors/module';
Palety kolorów
Mapowanie kolorów
Kolory powinny zostać zmapowane, a ich nazwy odzwierciedlać ich znaczenie - jeśli używamy Sass:
$app-colors: (
'primary': #8e3329,
'accent': #d98328,
'secondary': #5a1321,
'foreground': #191919,
'background': #e9e9e9
);
Odwołujemy się do nich za pomocą funkcji:
@function app-color($key: 'primary') {
@return map-get($app-colors, $key);
}
// Example:
$button-color: app-color('primary'); // #8e3329
Funkcja rozjaśniająca/przyciemniająca
Kolorów w palecie nie powinno być za wiele (około 4-7), do pozyskiwania większej ilości odcieni możemy skorzystać z funkcji rozjaśniającej/przyciemniającej dany kolor:
$color-interval: 10% !global;
@function app-color-level($color-name: 'primary', $level: 0) {
$color: app-color($color-name);
$color-base: if($level < 0, black, white);
@return mix($color-base, $color, $level * $color-interval);
}
// Example:
.panel {
background-color: app-color-level('primary', 2);
}
Funkcja ustalania przezroczystości
Do ustalania przezroczystości koloru używamy przykładowej funkcji:
$app-opacity: (
'light': 0.8, // opacity used with lighter colors
'dark': 0.4 // opacity used with darker colors
// ... etc.
);
@function app-color-alpha($name: 'primary', $opacity: 0) {
$color: app-color($name);
// Get the named opacity level, if it exists
@if map-key-exists($app-opacity, $opacity) {
$opacity: map-get($app-opacity, $opacity);
}
// Use rgba() to manipulate the color's alpha level
@return rgba($color, $opacity);
}
// Example usage:
$button-transparent-color: app-color-alpha('primary', 'light');
// => rgba(#8e3329, 0.8)
Typografia
Rozmiar
Podobnie jak w przypadku kolorów, mapujemy rozmiary fontów:
$type-scale: (
-1: 0.75rem, // small text
0: 1rem, // body text
1: 1.333rem, // large text
2: 1.777rem // main heading
);
@function type-scale($level) {
@return map-get($type-scale, $level);
}
Wysokość linii
Mapujemy również wysokości poszczególnych linii:
$base-font-size: 1rem;
$base-line-height: $base-font-size * 1.25;
$line-heights: (
-1: $base-line-height,
0: $base-line-height,
1: $base-line-height * 2,
2: $base-line-height * 2
);
// Again, we can make a helper function:
@function line-height($level) {
@return map-get($line-heights, $level);
}
Użycie
W celu użycia zdefiniowanych powyżej właściwości korzystamy z mixina:
@mixin type-setting($level: 0) {
font-size: type-scale($level);
line-height: line-height($level);
}
// The main heading
.heading-1 { @include type-setting(2); }
// The smaller top heading
.heading-2 { @include type-setting(-1); }
.paragraph { @include type-setting(0); }
.recipe-value { @include type-setting(1); }
.recipe-text { @include type-setting(-1); }
.recipe-button { @include type-setting(-1); }