Зарегистрируйтесь, чтобы продолжить обучение

Создание пользовательского компонента Bootstrap 5: Продвинутый уровень

При разработке нового сайта может не хватить стандартных компонентов. В этом случае можно пойти двумя путями:

  • Переработать дизайн и подстроиться под готовые компоненты фреймворка

  • Создать новые компоненты под свои нужды

Благодаря функциям, переменным и миксинам в Bootstrap создать новый компонент будет не сложно. Главное — понимать принципы работы Bootstrap и использовать все возможности.

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

Внешний вид компонента и его финальную верстку можно увидеть в CodePen ниже:

Процесс создания компонента разделим на несколько этапов:

  1. Определение структуры компонентов

  2. Верстка базовой структуры

  3. Верстка классов-оформления для придания компоненту различных цветовых схем

Структура компонента

Перед созданием стилей нужно определить, какие элементы будут использоваться в компоненте, и где будут нужны модификаторы. Структурно можно разбить компонент на следующие составляющие:

  • Главная обертка. Компонент называется citation. Класс будет выбран соответствующий. Блоки цитат должны иметь различные варианты оформления в виде изменения фона и цвета текста. В качестве цветов будут использованы значения из переменной $theme-colors

  • Обертка для текста. Это блок с телом цитаты. Хоть данная обертка может не всегда быть нужна, как в случае с одной строкой текста, но при сложных цитатах желательно иметь свою обертку. В качестве класса можно выбрать класс .citation-body

  • Обертка для автора цитаты. Помимо имени автора она создает границу сверху для разделения частей компонента. Данная область может иметь и ссылки на цитаты, поэтому блок можно назвать .citation-footer без привязки к автору

Верстка базовой структуры

Создадим одну базовую разметку для компонента:

<blockquote class="citation citation-success">
  <div class="citation-body">Основная задача не в том, чтобы найти ошибку. А в том, чтобы найти условия, при которых код продолжает свою работу</div>
  <div class="citation-footer">
    <cite>Кирилл Мокевнин</cite>
  </div>
</blockquote>

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

Второй этап создания компонента — создание файловой структуры. В Bootstrap каждый компонент располагается в отдельном файле. Также необходимо создать отдельный файл, где будет подключение Bootstrap и самого компонента. Таким файлом будет main.scss.

Общий вид файловой структуры:

bootstrap-project/
├── app/
│   ├── scss/
│   │   ├── main.scss
│   │   └── component/
│   │       └── _citation.scss
|   └── index.pug
├── build/
├── node_modules/
├── package-lock.json
├── package.json
└── gulpfile.js

В файле main.scss_ подключим Bootstrap и компонент Citation:

@import "../../node_modules/bootstrap/scss/bootstrap";
@import "./component/citation";

Теперь можно перейти к верстке блока цитат. В Bootstrap существуют свои стили для цитат и для этого есть четыре переменные в файле _variables.scss. Их можно использовать во время разработки компонента. Это поможет сохранить преемственность нашего компонента и стандартных стилей цитат.

$blockquote-margin-y:         $spacer !default;
$blockquote-font-size:        $font-size-base * 1.25 !default;
$blockquote-footer-color:     $gray-600 !default;
$blockquote-footer-font-size: $small-font-size !default;

Для создания отступов воспользуемся массивом $spacers, который имеет следующую структуру:

$spacer: 1rem !default;
$spacers: (
  0: 0,
  1: $spacer * .25,
  2: $spacer * .5,
  3: $spacer,
  4: $spacer * 1.5,
  5: $spacer * 3,
) !default;

Все эти значения помогут создать структуру блока .citation:

@use "sass:map";

$citation-padding: map.get($spacers, 5) map.get($spacers, 4) map.get($spacers, 3);
$citation-color: $blockquote-footer-color;
$citation-bg: transparent;
$citation-font-size: $blockquote-font-size;
$citation-border-radius: $border-radius;

.citation {
  --#{$prefix}citation-padding: #{$citation-padding};
  --#{$prefix}citation-color: #{$citation-color};
  --#{$prefix}citation-bg: #{$citation-bg};
  --#{$prefix}citation-font-size: #{$citation-font-size};
  --#{$prefix}citation-border-radius: #{$citation-border-radius};

  position: relative;

  display: block;

  margin: 0;
  padding: var(--#{$prefix}citation-padding);

  color: var(--#{$prefix}citation-color);
  font-size: var(--#{$prefix}citation-font-size);

  background-color: var(--#{$prefix}citation-bg);

  border-radius: var(--#{$prefix}citation-border-radius);
  @include box-shadow($box-shadow);
}

В этом примере основные свойства, такие как отступы, цвет, размеры вынесены в CSS-переменные. Этот подход появился в последних версиях Bootstrap и используется для создания тем. Главным триггером появления такого подхода стала возможность использования светлой и темной темы.

Создание кавычек в компоненте

Для создания кавычек воспользуемся псевдоэлементом ::before, который создаст новый элемент сразу после открытия тега с классом citation. Внутри псевдоэлемента используем абсолютно позиционированный элемент со шрифтом «Times New Roman». Для этого создадим переменную $font-family-serif в файле main.scss:

$enable-shadows: true; // включаем миксин box-shadow
$font-family-serif: "Times New Roman", Times, serif;

@import "../node_modules/bootstrap/scss/bootstrap";
@import "./citation";

Теперь все готово для создания псевдоэлемента:

@use "sass:map";

$citation-padding: map.get($spacers, 5) map.get($spacers, 4) map.get($spacers, 3);
$citation-color: $blockquote-footer-color;
$citation-bg: transparent;
$citation-font-size: $blockquote-font-size;
$citation-border-radius: $border-radius;

$citation-before-top: map.get($spacers, 4) * -1;
$citation-before-font-size: map.get($display-font-sizes, 1);
$citation-before-font-family: $font-family-serif;

.citation {
  --#{$prefix}citation-padding: #{$citation-padding};
  --#{$prefix}citation-color: #{$citation-color};
  --#{$prefix}citation-bg: #{$citation-bg};
  --#{$prefix}citation-font-size: #{$citation-font-size};
  --#{$prefix}citation-border-radius: #{$citation-border-radius};
  --#{$prefix}citation-before-top: #{$citation-before-top};
  --#{$prefix}citation-before-font-size: #{$citation-before-font-size};
  --#{$prefix}citation-before-font-family: #{$citation-before-font-family};

  position: relative;

  display: block;

  margin: 0;
  padding: var(--#{$prefix}citation-padding);

  color: var(--#{$prefix}citation-color);
  font-size: var(--#{$prefix}citation-font-size);

  background-color: var(--#{$prefix}citation-bg);

  border-radius: var(--#{$prefix}citation-border-radius);
  @include box-shadow($box-shadow);

  &::before {
    position: absolute;
    top: var(--#{$prefix}citation-before-top);

    font-size: var(--#{$prefix}citation-before-font-size);
    font-family: var(--#{$prefix}citation-before-font-family);

    content: "“";
  }
}

Создание футера компонента

Основная верстка контейнера для цитат готова. Теперь можно перейти к созданию стилей для .citation-footer. Можно обратить внимание, что пропущены стили для .citation-body. Это сделано по причине того, что все необходимые стили будут унаследованы от родительского блока .citation. В будущем эту обертку можно использовать для указания классов-утилит Bootstrap или создания новых модификаторов.

Задача футера — указать наклонное начертание шрифта и установить границу сверху вместе со всеми отступами. Так как автор цитаты всегда указывается шрифтом меньшим, чем сама цитата, воспользуемся переменной $blockquote-footer-font-size:

@use "sass:map";

$citation-padding: map.get($spacers, 5) map.get($spacers, 4) map.get($spacers, 3);
$citation-color: $blockquote-footer-color;
$citation-bg: transparent;
$citation-font-size: $blockquote-font-size;
$citation-border-radius: $border-radius;

$citation-before-top: map.get($spacers, 4) * -1;
$citation-before-font-size: map.get($display-font-sizes, 1);
$citation-before-font-family: $font-family-serif;

$citation-footer-margin: $spacer 0 0;
$citation-footer-padding: map.get($spacers, 2) 0 0;
$citation-footer-font-size: $blockquote-footer-font-size;
$citation-footer-border: 1px solid;

.citation {
  --#{$prefix}citation-padding: #{$citation-padding};
  --#{$prefix}citation-color: #{$citation-color};
  --#{$prefix}citation-bg: #{$citation-bg};
  --#{$prefix}citation-font-size: #{$citation-font-size};
  --#{$prefix}citation-border-radius: #{$citation-border-radius};
  --#{$prefix}citation-before-top: #{$citation-before-top};
  --#{$prefix}citation-before-font-size: #{$citation-before-font-size};
  --#{$prefix}citation-before-font-family: #{$citation-before-font-family};
  --#{$prefix}citation-footer-margin: #{$citation-footer-margin};
  --#{$prefix}citation-footer-padding: #{$citation-footer-padding};
  --#{$prefix}citation-footer-font-size: #{$citation-footer-font-size};
  --#{$prefix}citation-footer-border: #{$citation-footer-border};

  position: relative;

  display: block;

  margin: 0;
  padding: var(--#{$prefix}citation-padding);

  color: var(--#{$prefix}citation-color);
  font-size: var(--#{$prefix}citation-font-size);

  background-color: var(--#{$prefix}citation-bg);

  border-radius: var(--#{$prefix}citation-border-radius);
  @include box-shadow($box-shadow);

  &::before {
    position: absolute;
    top: var(--#{$prefix}citation-before-top);

    font-size: var(--#{$prefix}citation-before-font-size);
    font-family: var(--#{$prefix}citation-before-font-family);

    content: "“";
  }

  & > &-footer {
    margin: var(--#{$prefix}citation-footer-margin);
    padding: var(--#{$prefix}citation-footer-padding);

    font-size: var(--#{$prefix}citation-footer-font-size);
    font-style: italic;

    border-top: var(--#{$prefix}citation-footer-border);
  }
}

Основная верстка компонента закончена. Если воспользоваться созданным компонентом, то получим следующий блок:

Создание классов-модификаторов цветового оформления

Последняя задача — создание классов-модификаторов, которые добавят фоновый цвет для цитат. Помимо этого эти классы должны переопределить цвет текста на белый для создания правильного контраста.

С массивом $theme-colors возможно пройтись по всем цветам и добавить свойство background-color. Массив $theme-colors имеет следующие значения:

$theme-colors: (
  "primary":    $primary,
  "secondary":  $secondary,
  "success":    $success,
  "info":       $info,
  "warning":    $warning,
  "danger":     $danger,
  "light":      $light,
  "dark":       $dark
) !default;

Так как это ассоциативный массив, то для его перебора можно воспользоваться функцией @each:

@each $color, $value in $theme-colors {
  .citation-#{$color} {
    --#{$prefix}citation-color: var(--#{$prefix}#{$color}-text-emphasis);
    --#{$prefix}citation-bg: var(--#{$prefix}#{$color}-bg-subtle);
  }
}

Здесь мы меняем только заданные переменные для замены цвета фона и текста. Для «красоты» были использованы не просто цвета, а их специальные версии, где фон осветляется, а текст становится темнее. Такой же подход используется в компоненте Alert.

В результате компиляции появятся следующие стили:

.citation-primary {
  --bs-citation-color: var(--bs-primary-text-emphasis);
  --bs-citation-bg: var(--bs-primary-bg-subtle);
}

.citation-secondary {
  --bs-citation-color: var(--bs-secondary-text-emphasis);
  --bs-citation-bg: var(--bs-secondary-bg-subtle);
}

.citation-success {
  --bs-citation-color: var(--bs-success-text-emphasis);
  --bs-citation-bg: var(--bs-success-bg-subtle);
}

.citation-info {
  --bs-citation-color: var(--bs-info-text-emphasis);
  --bs-citation-bg: var(--bs-info-bg-subtle);
}

.citation-warning {
  --bs-citation-color: var(--bs-warning-text-emphasis);
  --bs-citation-bg: var(--bs-warning-bg-subtle);
}

.citation-danger {
  --bs-citation-color: var(--bs-danger-text-emphasis);
  --bs-citation-bg: var(--bs-danger-bg-subtle);
}

.citation-light {
  --bs-citation-color: var(--bs-light-text-emphasis);
  --bs-citation-bg: var(--bs-light-bg-subtle);
}

.citation-dark {
  --bs-citation-color: var(--bs-dark-text-emphasis);
  --bs-citation-bg: var(--bs-dark-bg-subtle);
}

Так как все цвета берутся из массива, то смена цветовой темы всего проекта приведет и к смене цветов этого компонента.

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

Выводы

В этом уроке мы изучили, как создаются пользовательские компоненты с помощью Bootstrap. Чтобы связать новый компонент с «внутренностями» фреймворка следует использовать:

  • Переменные Bootstrap, которые находятся в файле \_variables.scss

  • Функции и миксины фреймворка

  • CSS-переменные

При таком подходе смена настроек фреймворка или его обновление затронет и ваши созданные компоненты. Это поможет держать систему в однообразии.


Самостоятельная работа

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


Дополнительные материалы

  1. Разработка пользовательских компонентов и утилит на Bootstrap [Хекслет]

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»