Статьи

Введение в Sass Maps: использование и примеры

Для масштабируемых интерфейсов Sass Maps — это благословение. Извлечение конфигурации из логики модуля — отличный способ структурирования. Позвольте мне объяснить вам, почему я считаю, что Sass Maps — лучшая функция в Sass 3.3.

Sass 3.3 уже давно доступен каждому, но многие из его реальных функций все еще незнакомы многим разработчикам. Новая версия Sass принесла нам новый тип данных с именем map . Карты содержат набор пар ключ / значение и помогают нам создавать небольшие области конфигурации для упрощенной базы кода.

Чтобы быть в курсе, мы рассмотрим основы использования Sass Maps, а затем рассмотрим некоторые варианты использования.

Вот краткий обзор синтаксиса для нахальной карты. Начните с имени переменной (в данном случае $map ), а затем введите несколько ключей со значениями, разделенными запятыми, все в фигурных скобках:

1
2
3
4
$map: (
    key: value,
    nextkey: nextvalue
);

Сохраняя несколько пар ключ / значение в какой-то момент, вам потребуется извлечь эту информацию. Если вам нужно найти значение ключа, используйте функцию map-get() . Мы собираемся передать ему два параметра: имя карты и затем ключ.

1
2
3
.element:before {
    content: map-get($map, key);
}

После компиляции вывод будет следующим:

1
2
3
.element:before {
    content: value;
}

Настоятельно рекомендуется использовать надежную обработку ошибок в процессе разработки Sass. Для этого Sass дает нам функцию map-has-key() . Этот помощник ищет, существует ли ключ, и, если нет, доставляет другой вывод, чтобы предупредить разработчика.

Взгляните на этот «Введение в обработку ошибок в Sass » Хьюго Жирауделя (Hugo Giraudel), чтобы узнать, как справляться с ошибками.

01
02
03
04
05
06
07
08
09
10
11
12
$map: (
    key: value,
    nextkey: nextvalue
);
 
.element {
  @if map-has-key($map, key) {
    content: ‘Map has this key.’;
  } @else {
    content: ‘Map has not this key.’;
  }
}

Результат:

1
2
3
.element {
  content: ‘Map has this key.’;
}

Бонусное время: Sass позволяет нам объединять две или более карты вместе. Теперь вы уже знакомы с этим, так что взгляните на этот пример использования функции map-merge() :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
$colors: (
  light: #ccc,
  dark: #000
);
 
$brand-colors: (
  main: red,
  alternative: blue
);
 
// Merge maps
$merged: map-merge($colors, $brand-colors);
 
.element {
  content: map-get($merged, alternative);
}

Результат:

1
2
3
.element {
  content: blue;
}

Мы рассмотрели как , теперь давайте посмотрим на где .

Карты также могут быть полезны без сопутствующих функций. Например, вы можете выполнить цикл по вашей карте, определить параметры со значениями, которые вы ожидаете, а затем добавить имя Sass Map. Делая это, можно работать с разными видами ценностей.

В этом примере я выводю классы для отображения значков. Я поставил имя значка в качестве ключа, оставив значение для хранения фактического content (который мы затем добавили бы через псевдоэлементы).

Примечание . В реальном сценарии мы сначала объявляем некоторые базовые стили, но это выходит за рамки данного руководства.

01
02
03
04
05
06
07
08
09
10
11
12
13
/* Define the Sassy Map called $icons */
$icons: (
  checkmark: a,
  plus: b,
  minus: c
);
 
/* For each key in the map, created an own class */
@each $name, $value in $icons {
  .icon—#{$name} {
    content: $value;
  }
}

Вывод говорит сам за себя:

01
02
03
04
05
06
07
08
09
10
11
12
/* For each key in the map, created an own class */
.icon—checkmark {
  content: «a»;
}
 
.icon—plus {
  content: «b»;
}
 
.icon—minus {
  content: «c»;
}

Это действительно эффективный способ вывода множества классов для иконок. Есть еще много вариантов использования — давайте посмотрим на некоторые.

Двигаясь дальше, можно дать ключу более одного значения. Это делается с помощью вырезок и ввода нескольких значений через запятую. Это, например, может быть полезно для переноса стилей для вариантов модуля.

Здесь я собираюсь стилизовать серию кнопок. Первое значение для каждого ключа — background-color а второе — font-color .

Затем я перебираю ключи с ожидаемым объектом $colors . Я получаю значение первого ключа в этом объекте с помощью nth($colors, 1) (начинаем с имени объекта, а затем положения искомого значения). Если вам нужно второе значение, введите 2 .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// _m-buttons.scss
$buttons: (
  error: (#d82d2d, #666),
  success: (#52bf4a, #fff),
  warning: (#c23435, #fff)
);
 
.m-button {
  display: inline-block;
  padding: .5em;
  background: #ccc;
  color: #666;
   
  @each $name, $colors in $buttons {
    $bgcolor: nth($colors, 1);
    $fontcolor: nth($colors, 2);
     
    &—#{$name} {
      background-color: $bgcolor;
      color: $fontcolor;
    }
  }
}

Выход:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
.m-button {
  display: inline-block;
  padding: .5em;
  background: #ccc;
  color: #666;
}
 
.m-button—error {
  background-color: #d82d2d;
  color: #666;
}
 
.m-button—success {
  background-color: #52bf4a;
  color: #fff;
}
 
.m-button—warning {
  background-color: #c23435;
  color: #fff;
}

Я не знаю ни одного фронтенд-разработчика, который бы в какой-то момент не боролся с z-index . Проблемы обычно возникают из-за потери обзора, если вам нужно использовать z-index в нескольких местах проекта. Sass карты могут помочь нам.

Давайте начнем с $layer в качестве карты. Ключи должны быть логически названы, чтобы вы знали, какое значение для какого элемента — может быть offcanvas , lightbox , dropdown offcanvas и т. Д.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
// _config.scss
$layer: (
  offcanvas: 1,
  lightbox: 500,
  dropdown: 10,
  tooltip: 15
);
 
// _m-lightboxes.scss
@function layer($name) {
  @if map-has-key($layer, $name) {
    @return map-get($layer, $name);
  }
   
  @warn «The key #{$name} is not in the map ‘$layer'»;
  @return null;
};
 
.m-lightbox {
  z-index: layer(lightbox);
}

Здесь я написал функцию для получения значения определенного ключа, но почему я это сделал? Ответ к счастью прост: это быстрее, чем писать map-get() каждый раз. Еще одним положительным моментом является то, что вы можете создать обработку ошибок и дать разработчику небольшую обратную связь о том, почему ничего не происходит.

Это вывод:

1
2
3
.m-lightbox {
  z-index: 500;
}

Каждый проект имеет свой собственный файл конфигурации; основы для глобального использования. Например, в моих проектах я определяю некоторые значения для свойств шрифта: font-color, альтернативный font-color, font-family или font-size. Я использовал для создания переменной для каждого свойства, но карта будет лучше.

Вот быстрый пример, чтобы начать со старого решения:

1
2
3
4
$base-font-color: #666;
$base-font-family: Arial, Helvetica, Sans-Serif;
$base-font-size: 16px;
$base-line-height: 1.4;

Затем новое решение с использованием карты Sass:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
// _config.scss
$font: (
  color: #666,
  family: (Arial, Helvetica),
  size: 16px,
  line-height: 1.4
);
 
// _presets.scss
body {
  color: map-get($font, color);
  font-family: map-get($font, family);
  font-size: map-get($font, size);
  line-height: map-get($font, line-height);
}

Я люблю этот вариант использования. Прекрасно иметь область для точек останова, которые есть во всем вашем проекте. Итак, как и в разделе об обработке с помощью z-index, у вас есть обзор всех используемых точек останова. Если вы измените значение там, то вы измените поведение на протяжении всего проекта. Потрясающие.

Итак, давайте начнем с карты под названием $breakpoints .

Наша цель — использовать точки останова с неявными именами вместо значений жестких пикселей в элементе. Из-за этого нам нужен миксин, который выведет значение указанного имени. Я назвал mixin response respond-to и передать $breakpoint в качестве параметра. С помощью $value я получаю значение ожидаемой точки останова и помещаю ее позже в медиа-запрос.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
// Map with much breakpoints
$breakpoints: (
    small: 320px,
    medium: 600px,
    large: 768px
);
 
// Respond-To Mixin
@mixin respond-to($breakpoint) {
    @if map-has-key($breakpoints, $breakpoint) {
        $value: map-get($breakpoints, $breakpoint);
         
        @media screen and (min-width: $value) {
            @content;
        }
    }
     
    @warn «Unknown `#{$breakpoint}` in $breakpoints»;
}

Пример:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
// Sass
.m-tabs {
    background-color: #f2f2f2;
     
    @include respond-to(medium) {
        background-color: #666;
    }
}
 
// Output
.m-tabs {
    background-color: #f2f2f2;
}
@media screen and (min-width: 600px) {
    background-color: #666;
}

Этот вариант использования является одним из моих любимых!

Вещи становятся немного хитрее сейчас. Давайте посмотрим на вложенные карты — потрясающе для цветовых схем с диапазоном тонов.

Наша карта Sass в этом случае получает имя $colorscheme и содержит объекты с ключами и значениями. У проекта разные серые тона, но мы не хотим объявлять переменную для каждого. Таким образом, мы добавляем gray объект, добавляем вырезки, а затем ключи со значениями.

Начните с карты вот этой:

01
02
03
04
05
06
07
08
09
10
11
12
13
// Scheme of colors
$colorscheme: (
  gray: (
    base: #ccc,
    light: #f2f2f2,
    dark: #666
  ),
  brown: (
    base: #ab906b,
    light: #ecdac3,
    dark: #5e421c
  )
);

Теперь давайте добавим функцию setcolor для более короткого способа выбора цвета. Первым ожидаемым значением является объект карты Sass ( $scheme ) — в этом примере оно может быть gray или brown . Второй параметр — это цвет, который вы хотите ( $tone ) — значение по умолчанию для этого является ключевой base .

1
2
3
4
// Our function for shorter usage of map-get();
@function setcolor($scheme, $tone: base) {
    @return map-get(map-get($colorscheme, $scheme), $tone);
}

Наконец, вот пример того, как вы можете использовать его и как вы получаете разные цвета от вложенной карты. Это проще, чем вы думаете (возможно)!

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
// Sass
.element {
  color: setcolor(brown);
}
.element—light {
  color: setcolor(brown, light);
}
 
// Output
.element {
    color: #ab906b;
}
.element—light {
    color: #ecdac3;
}

Вы выполнили задание Теперь вы можете создать палитру, не разбрасывая код слишком большим количеством переменных для каждого типа цвета.

На эту технику меня вдохновил Том Дэвис, и я рекомендую вам ознакомиться с его статьей по этому вопросу.

Теперь кое-что для продвинутых пользователей Sass. В проектах часто требуется создавать различные виды тем с одной и той же кодовой базой. Итак, вот предложение установить класс темы в верхней части документа, чтобы применить определенный вид. Нам нужен объект, где мы можем обработать имя темы и установить различные стили для модуля.

Начните с карты Sass и определите темы глобально для вашего проекта. Значение — это имя и класс, который необходимо добавить к элементу <body> . В этом примере я создал карту $themes с двумя вариантами: theme-light и theme-dark .

1
2
3
4
5
// _config.scss
$themes: (
  theme1: theme-light,
  theme2: theme-dark
);

Теперь нам нужна функция для быстрого получения значений модулей. Это краткий помощник и нуждается в трех параметрах. Эти:

  • $map : определить имя карты, откуда берутся все значения.
  • $object : в этом случае ключ для темы.
  • $style : свойство для стиля, который необходим.
1
2
3
4
5
6
7
8
// _functions.scss
@function setStyle($map, $object, $style) {
  @if map-has-key($map, $object) {
    @return map-get(map-get($map, $object), $style);
  }
  @warn «The key ´#{$object} is not available in the map.»;
  @return null;
}

Теперь создайте новую Sass Map с именем $config . Каждая тема получает объект, и имя должно совпадать с ключом, который вы определили в $themes : в противном случае вы получите ошибку.

01
02
03
04
05
06
07
08
09
10
11
12
// _m-buttons.scss
// 1.Config
$config: (
  theme1: (
    background: #f2f2f2,
    color: #000
  ),
  theme2: (
    background: #666,
    color: #fff
  )
);

Наконец часть с небольшим количеством магии. Мы начинаем с такого модуля, как .m-button а затем хотим создать новый вид в каждой теме. Поэтому мы используем @each с $key и $value качестве ожидаемых значений, которые мы получаем из тем Map $themes . Теперь Sass просматривает ключи на карте и создает что-то для каждой темы.

В начале этого раздела я упомянул, что необходимо, чтобы ключи были одинаковыми на каждой карте ( $themes и $config ). Поэтому мы должны проверить, есть ли у карты $ config ключ от карты $themes , поэтому используйте функцию map-has-key() . Если ключ доступен, сделайте следующее, иначе выведите ошибку, чтобы сообщить разработчику.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
// _m-buttons.scss
// 2.Base
.m-button {
  @each $key, $value in $themes {
    @if map-has-key($config, $key) {
      .#{$value} & {
        background: setStyle($config, $key, background);
        color: setStyle($config, $key, color);
      }
    } @else {
      @warn «The key ´#{$key} isn’t defined in the map $config´»
    }
  }
}

После всего написанного кода, давайте посмотрим на результат. Превосходно, что область конфигурации отделена от логики модуля.

1
2
3
4
5
6
7
8
.theme-light .m-button {
  background: #f2f2f2;
  color: #000;
}
.theme-dark .m-button {
  background: #666;
  color: #fff;
}

Наконец пришло время попробовать это самостоятельно. Возможно, это решение не работает для вас, и вам нужно другое, но в целом я надеюсь, что оно поможет вам хорошо поддерживать ваш код. Вы можете поиграть с этим примером на Codepen:

На мой взгляд, Sass Maps были лучшей функцией, представленной в Sass 3.3. Лично я считаю, что это отличный способ улучшить структуру вашего фонда и создать небольшие области конфигурации. Карты Sass упрощают обработку и изменение значений, не влияя на логику всей кодовой базы. Начните использовать их сегодня, ваши коллеги будут благодарны!

Если вы уже используете карты Sass, сообщите нам, как вы используете их в своих проектах!