Система компонентов CSS · Новый ресурс

Дизайн-система Bootstrap.

Используйте Bootstrap 5.3.8 и его реальную шкалу отступов, семантические цвета, адаптивную сетку и API компонентов. Проверьте работающую форму бронирования, сводку ошибок, фильтр таблицы, модальное окно и переключатель цветовой схемы, а затем используйте приведённый код.

Руководство OpenDesign8 глав66 справочных записейАвторское руководство по приложению
01

Предварительный просмотр интерфейса дизайн-системы Bootstrap

Фильтруйте бронирования, проверяйте поля, просматривайте данные в нативном модальном окне и переключайтесь между светлой и тёмной темами.

Бронирование оборудования · Bootstrap 5.3.8Открыть полный пример
Нативные Bootstrap 5.3.8 CSS и JavaScript, загружаемые локально. Данные о бронировании и поведение приложения приведены только в качестве примера. · Справочник по реализации
02

Справочник по дизайну системы дизайн-система Bootstrap

Скомпилированные значения Bootstrap 5.3.8 по умолчанию CSS и документация версии 5.3. Значения приведены по умолчанию и не являются обязательными правилами бренда. Сравнение rem с пикселями предполагает корневой размер шрифта 16px; на меньших экранах адаптивные размеры шрифта могут отличаться от значений для больших экранов. У окружающей страницы OpenDesign остаётся собственная типографика.

Семантические цвета и роли поверхностей

Источник
Название / правилоЗначение / конфигурацияПрименение
--bs-primary#0d6efd Базовый цвет основных действий и ссылок.
--bs-secondary#6c757d Дополнительное семейство цветов темы; это не адаптивная роль вторичного цвета основного текста.
--bs-success#198754 Базовый цвет позитивного статуса; дополните его текстовой меткой.
--bs-danger#dc3545 Базовый цвет темы ошибки или деструктивного действия.
--bs-warning#ffc107 Базовый цвет темы предупреждения; проверьте контрастность текста.
--bs-info#0dcaf0 Базовый цвет информационной темы.
--bs-body-bg#fffПоверхность страницы в светлой теме.
--bs-body-color#212529 Цвет основного текста в светлой теме.
--bs-secondary-bg#e9ecef Вторичная поверхность в светлой теме.
--bs-tertiary-bg#f8f9fa Ненавязчивая поверхность панели в светлой теме.
--bs-primary-bg-subtle#cfe2ff Тонированная поверхность основного цвета в светлой теме.
--bs-primary-text-emphasis#052c65 Текст для поверхностей с лёгким оттенком основного цвета.
--bs-border-color#dee2e6 Роль границы в светлой теме.

Типографика основного текста и удобная для чтения иерархия

Источник
Название / правилоЗначение / конфигурацияПрименение
--bs-body-font-size1remРазмер основного текста по умолчанию: 1rem, обычно 16px.
--bs-body-line-height1.5Множитель без единиц измерения: обычно высота строки составляет 24px.
--bs-body-font-weight400Обычная насыщенность основного текста.
--bs-body-font-familyvar(--bs-font-sans-serif)Системный стек интерфейса, предоставляемый Bootstrap.
--bs-font-monospaceSFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospaceДля кода и технических значений используется моноширинный стек.

Размеры заголовков и утилиты для крупного текста

Источник
Название / правилоЗначение / конфигурацияПрименение
h1 / .h12.5remРазмер для больших экранов; для h1–h4 по умолчанию используется адаптивный размер шрифта.
h2 / .h22remРазмер для больших экранов; для h1–h4 по умолчанию используется адаптивный размер шрифта.
h3 / .h31.75remРазмер для больших экранов; для h1–h4 по умолчанию используется адаптивный размер шрифта.
h4 / .h41.5remРазмер для больших экранов; для h1–h4 по умолчанию используется адаптивный размер шрифта.
h5 / .h51.25remФиксированный размер заголовка по умолчанию.
h6 / .h61remФиксированный размер заголовка по умолчанию.
.lead1.25rem / weight 300Вводный текст; не заменяет заголовок.
.small0.875emОтносительно мелкий текст; используйте выборочно для метаданных.

Шкала утилит отступов

Источник
Название / правилоЗначение / конфигурацияПрименение
00Используйте с утилитами m/p/gap/g; например, p-0.
10.25remИспользуйте с утилитами m/p/gap/g; например, p-1.
20.5remИспользуйте с утилитами m/p/gap/g; например, p-2.
31remИспользуйте с утилитами m/p/gap/g; например, p-3.
41.5remИспользуйте с утилитами m/p/gap/g; например, p-4.
53remИспользуйте с утилитами m/p/gap/g; например, p-5.
ms / meinline start / endЛогическое обозначение сторон; в отличие от ml/mr в более старых версиях Bootstrap.
p-3 p-md-41rem → 1.5rem at mdАдаптивный внутренний отступ, используемый в примере.
gap-20.5remРасстояние между дочерними элементами flex/grid.

Адаптивные пороги сетки

Источник
Название / правилоЗначение / конфигурацияПрименение
xs / .col-0Базовый уровень, без префикса xs.
sm / .col-sm-576pxМалый уровень; максимальная ширина .container — 540px.
md / .col-md-768pxСредний уровень; максимальная ширина .container — 720px.
lg / .col-lg-992pxБольшой уровень; максимальная ширина .container — 960px.
xl / .col-xl-1200pxОчень большой уровень; максимальная ширина .container — 1140px.
xxl / .col-xxl-1400pxСамый большой уровень по умолчанию; максимальная ширина .container — 1320px.
Grid columns12Сочетание col-lg-7 и col-lg-5 заполняет одну строку.
Default horizontal gutter1.5remВнутренний отступ столбца — 0.75rem с каждой стороны; строка компенсирует его отрицательными внешними отступами.

Скругление границ и высота тени

Источник
Название / правилоЗначение / конфигурацияПрименение
--bs-border-width1pxТолщина границы по умолчанию.
--bs-border-radius0.375remПоля, карточки и скругление углов по умолчанию.
--bs-border-radius-sm0.25remКомпактное скругление.
--bs-border-radius-lg0.5remБолее выраженное скругление.
--bs-border-radius-xl1remСильное скругление поверхности.
--bs-border-radius-xxl2remОчень сильное скругление поверхности.
--bs-border-radius-pill50remФорма капсулы, а не измеренный радиус компонента.
--bs-box-shadow-sm0 0.125rem 0.25rem rgba(0, 0, 0, 0.075)Ненавязчивая тень.
--bs-box-shadow0 0.5rem 1rem rgba(0, 0, 0, 0.15)Высота по умолчанию.
--bs-box-shadow-lg0 1rem 3rem rgba(0, 0, 0, 0.175)Выраженная тень; не применяйте её ко всем поверхностям.

Размеры кнопок и переменные состояний

Источник
Название / правилоЗначение / конфигурацияПрименение
--bs-btn-padding-x0.75remГоризонтальный внутренний отступ кнопки по умолчанию.
--bs-btn-padding-y0.375remВертикальный внутренний отступ кнопки по умолчанию.
--bs-btn-font-size1remРазмер текста кнопки по умолчанию.
--bs-btn-line-height1.5Множитель высоты строки текста кнопки по умолчанию.
--bs-btn-border-width1pxТолщина границы по умолчанию.
--bs-btn-border-radiusvar(--bs-border-radius)Радиус скругления кнопки по умолчанию.
--bs-btn-disabled-opacity0.65Визуальное оформление; также используйте настоящий атрибут disabled.

Изменение ролей в светлой и тёмной темах

Источник
Название / правилоЗначение / конфигурацияПрименение
--bs-body-bglight #fff / dark #212529Фон страницы зависит от data-bs-theme.
--bs-body-colorlight #212529 / dark #dee2e6Цвет текста адаптируется к поверхности.
--bs-border-colorlight #dee2e6 / dark #495057Граница, адаптирующаяся к теме.
--bs-primary-bg-subtlelight #cfe2ff / dark #031633Фон с оттенком статуса меняется в зависимости от темы.
--bs-primary-text-emphasislight #052c65 / dark #6ea8feИспользуйте вместе с соответствующей поверхностью с лёгким оттенком.
data-bs-themelight | darkЗадайте на уровне всего html или локальной вложенной области.
03

Полное руководство по дизайн-системе Bootstrap

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

DESIGN-bootstrap.md

Подробные рекомендации, отправная точка для реализации и ссылки на источники.

Скачать руководство

Дизайн-система Bootstrap: выберите CSS и обязанности JavaScript для Bootstrap

Одна таблица стилей, поведение компонентов — по желанию

Скомпилированная таблица стилей Bootstrap предоставляет сетку, типографику, утилиты и оформление компонентов. Пакет JavaScript добавляет интерактивные плагины, например Modal, Collapse и Dropdown. Для стилизованной кнопки JavaScript не нужен, а для запуска модального окна через data-bs-toggle — нужен. В рабочем предварительном просмотре локально загружаются соответствующие таблица стилей и пакет версии 5.3.8, чтобы элементы управления демонстрировали реальные принципы их работы.

Из этого руководства OpenDesign

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

  • CSS: макет, типографика, кнопки, поля, таблицы и оформление состояний.
  • Bootstrap JavaScript: открытие модального окна, фон-затемнение, реакция на Escape и управление фокусом.
  • JavaScript приложения: сообщения проверки, фильтрация записей и локальное обновление данных.

Прочитать вспомогательную спецификацию

Выберите скомпилированный CSS или сборку Sass

Выберите скомпилированный CSS для быстрого старта или продукта, в котором можно использовать стандартный набор утилит. Исходный код Sass подойдёт, если нужно изменить карты темы, генерацию утилит или сетку на этапе сборки. Пользовательские свойства CSS во время выполнения подходят для настройки отдельных компонентов, но изменение корневой цветовой переменной не пересобирает все заранее скомпилированные варианты.

scss
$primary: #3159a5;
$border-radius: .5rem;
@import "bootstrap/scss/bootstrap";

Справочник по коду

Прочитать вспомогательную спецификацию

Дизайн-система Bootstrap: семантические цвета и цветовые режимы

Сочетайте поверхность статуса с соответствующим цветом текста

Для значков бронирования используются bg-primary-subtle и text-primary-emphasis. Это парные семантические роли: цвет текста и фон адаптируются при изменении data-bs-theme. Однотонный синий фон в сочетании с произвольным серым текстом лишает их этой связи. Кроме того, статусы «Забронировано», «Используется» и «Черновик» по-прежнему обозначены текстом: цвет — не единственный способ передать их смысл.

html
<span class="badge text-primary-emphasis bg-primary-subtle">Reserved</span>
<section data-bs-theme="dark">
  <div class="bg-body text-body border rounded p-3">Theme-scoped content</div>
</section>

Справочник по коду

Прочитать вспомогательную спецификацию

Ограничивайте настройку рамками компонента

Для отдельного пользовательского действия переопределите локальные свойства --bs-btn-*. Задайте значения не только для обычного фона, но и для состояний hover и active. Пример ниже показывает вариант для приложения, а не значение по умолчанию в Bootstrap. Применяйте этот класс только к нужной кнопке, чтобы он случайно не повлиял на все основные действия в другой части страницы.

css
.btn-reserve {
  --bs-btn-color: #fff;
  --bs-btn-bg: #3159a5;
  --bs-btn-border-color: #3159a5;
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: #274783;
  --bs-btn-hover-border-color: #274783;
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: #203a6b;
  --bs-btn-active-border-color: #203a6b;
}

Справочник по коду

Прочитать вспомогательную спецификацию

Дизайн-система Bootstrap: используйте фактическую шкалу типографики

Разделяйте семантику документа и визуальный размер

Главный заголовок предварительного просмотра — элемент h1 с классом h3: он остаётся основным заголовком страницы, но использует меньший визуальный размер, подходящий для инструмента. Заголовки разделов — элементы h2 со стилем h5. Bootstrap предоставляет стили как для самих элементов, так и для соответствующих классов заголовков, позволяя разделить семантику и оформление без пропуска уровней в структуре документа.

Размер основного текста по умолчанию — 1rem, высота строки — 1.5. Размеры от h1 до h4 адаптивно увеличиваются и достигают значений из справочной таблицы. Поэтому снимок экрана при одной ширине не отражает всю шкалу типографики. Используйте скомпилированные стили или описанное поведение Sass, а не копируйте размер в пикселях, измеренный в одном окне просмотра.

Прочитать вспомогательную спецификацию

Назначьте вторичному тексту роль, адаптирующуюся к теме

text-body-secondary зависит от цветового режима основного текста. Этот стиль подходит для дополнительной информации о записи, например имени владельца под названием оборудования. Класс small уменьшает текст относительно окружающего, поэтому его не следует применять ко всем подписям полей: форму станет сложнее быстро просматривать. Оставляйте подписи в стандартном размере формы, а компактный текст используйте для подсказок и метаданных.

html
<h1 class="h3">Equipment reservations</h1>
<p class="text-body-secondary">Review availability before booking.</p>
<small class="text-body-secondary">Local demonstration data</small>

Справочник по коду

Прочитать вспомогательную спецификацию

Дизайн-система Bootstrap: создавайте макеты с помощью утилит отступов и сетки

Используйте шкалу вместо произвольных интервалов

p-3 задаёт внутренний отступ 1rem, p-4 — 1.5rem, а p-5 увеличивает его до 3rem. Обозначения — это ключи шкалы, а не значения в пикселях. В примере используется p-3 p-md-4: при ширине 768px внешний внутренний отступ увеличивается, а mb-3 разделяет группы полей интервалом 1rem. Это правило относится к данному примеру и не создаёт новую официальную шкалу отступов.

html
<div class="p-3 p-md-4">
  <div class="d-flex flex-wrap gap-2 mb-3">
    <button class="btn btn-primary">Review</button>
    <button class="btn btn-outline-secondary">Reset</button>
  </div>
</div>

Справочник по коду

Прочитать вспомогательную спецификацию

Сохраняйте связь между строками и столбцами

Прочитать вспомогательную спецификацию

Дизайн-система Bootstrap: создавайте поля с явными связями

Свяжите подписи, подсказки и сообщения об ошибках

form-label оформляет настоящую метку; её значение for должно совпадать с id поля ввода. form-control оформляет текстовые поля ввода, а form-select — список выбора. В примере aria-describedby связывает поле с подсказкой и сообщением об ошибке, а required задаёт реальное ограничение. Имена классов сами по себе не создают эти семантические связи.

html
<label for="equipment" class="form-label">Equipment</label>
<select id="equipment" class="form-select" required
  aria-describedby="equipment-error">
  <option value="">Choose equipment</option>
  <option>Camera kit A</option>
</select>
<div class="invalid-feedback" id="equipment-error">Choose equipment.</div>

Справочник по коду

Прочитать вспомогательную спецификацию

Используйте настоящее состояние ошибки и доступную сводку

При отправке примера проверяется каждое поле, задаются is-invalid и aria-invalid, создаются текстовые ссылки на поля с ошибками, а фокус переводится на сводку. Исправление поля обновляет его состояние, не удаляя другие ответы. Этот прикладной слой необходим: в документации Bootstrap предупреждается, что одни лишь пользовательские визуальные подсказки не полностью доступны вспомогательным технологиям.

  1. Перед тем как отметить поле как ошибочное, проверьте результат фактической проверки ограничений.
  2. Свяжите текст ошибки с полем и сообщите о его недопустимом состоянии.
  3. После отправки переместите фокус на полезную сводку или первое поле с ошибкой.

Прочитать вспомогательную спецификацию

Дизайн-система Bootstrap: показывайте записи и фильтруйте их, сохраняя смысл

Используйте компонент таблицы для сопоставимых данных

В таблице есть заголовки столбцов и строк, а также подпись. table-hover добавляет подсветку при наведении, но не превращает строки в кнопки. Фильтрация скрывает подходящие строки и обновляет число результатов в области aria-live. Статус показан текстом внутри бейджа, поэтому его смысл сохраняется при смене цветового режима.

html
<div class="table-responsive">
  <table class="table table-hover">
    <caption>Fictional equipment reservations</caption>
    <thead><tr><th scope="col">Equipment</th><th scope="col">Status</th></tr></thead>
    <tbody><tr><th scope="row">Camera kit A</th><td>Reserved</td></tr></tbody>
  </table>
</div>

Справочник по коду

Прочитать вспомогательную спецификацию

Ограничьте прокрутку таблицы областью данных

table-responsive добавляет горизонтальную прокрутку, если широкая таблица не помещается. Не размещайте внутри этой обёртки выпадающий список, которому нужно выходить за её границы, не проверив его поведение. В примере фильтр находится над таблицей. На мобильных устройствах горизонтально прокручиваться может только область данных; сама страница должна помещаться в окне просмотра.

Прочитать вспомогательную спецификацию

Дизайн-система Bootstrap: проверьте выбор в модальном окне API

Открывайте окно, только если форма прошла проверку

Интерактивный пример создаёт экземпляр Bootstrap Modal или использует уже существующий и вызывает show только после успешной проверки. Так слой проверки не перекрывает ошибки, требующие внимания. Текст заполняется текущими значениями; при выборе «Изменить данные» модальное окно закрывается, а данные формы сохраняются.

javascript
const element = document.getElementById("review-modal");
const modal = bootstrap.Modal.getOrCreateInstance(element);
// Run after validation and after populating the review text.
modal.show();
element.addEventListener("hidden.bs.modal", () => {
  document.querySelector("#reservation button[type=submit]").focus();
});

Справочник по коду

Прочитать вспомогательную спецификацию

Учитывайте жизненный цикл компонента модального окна

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

Прочитать вспомогательную спецификацию

Дизайн-система Bootstrap: интегрируйте и расширяйте этот пример Bootstrap

Подключите соответствующие версии CSS и JavaScript

Встроенный пример использует локально сохранённые файлы Bootstrap 5.3.8 CSS и bundle. Атрибуты данных и API Modal взяты из этого релиза. В приложении Vite импортируйте скомпилированный CSS и необходимый плагин, как показано в разделе настройки. Не подключайте bundle и не запускайте вторую копию того же плагина через другую обёртку.

Прочитать вспомогательную спецификацию

Расширяйте пример в соответствии с контрактом компонента

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

Прочитать вспомогательную спецификацию

Примеры компонентов дизайн-системы Bootstrap

index.html — полный пример бронирования

Полная страница Bootstrap 5.3.8 со стилями, средой выполнения модального окна, проверкой, фильтрами и локальным подтверждением. Сохраните этот файл как index.html и запустите сервер в папке командой ниже. Для закреплённых зависимостей CDN требуется подключение к сети.

html
<!doctype html><html lang="en" data-bs-theme="light"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Bootstrap equipment reservations — OpenDesign example</title><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"><style>body{margin:0}main{max-width:1120px;margin:auto}.demo-stat{font-variant-numeric:tabular-nums}.table td,.table th{vertical-align:middle}.table caption{font-size:.875rem}.demo-status:empty{display:none}@media(max-width:575px){.table th,.table td{font-size:.8125rem;padding:.65rem .4rem}.demo-mobile-hide{display:none}}@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important}}</style></head><body>
<header class="border-bottom bg-body-tertiary px-3 px-md-4 py-3 d-flex align-items-center justify-content-between gap-3"><div><strong>Studio inventory</strong><span class="badge text-bg-primary ms-2">Bootstrap 5.3.8</span></div><button id="theme" type="button" class="btn btn-outline-secondary btn-sm" aria-pressed="false">Dark mode</button></header>
<main class="p-3 p-md-4"><div class="d-flex align-items-start justify-content-between gap-3 mb-4"><div><p class="text-body-secondary small mb-1">EQUIPMENT / RESERVATIONS</p><h1 class="h3 mb-2">Keep the next shoot ready.</h1><p class="text-body-secondary mb-0">Check equipment, create a local reservation and review its details.</p></div><span class="badge rounded-pill text-primary-emphasis bg-primary-subtle border border-primary-subtle demo-mobile-hide">Interactive example</span></div>
<div class="row g-3 mb-4"><div class="col-4"><div class="border rounded p-3"><div class="text-body-secondary small">Equipment</div><strong class="fs-3 demo-stat">12</strong></div></div><div class="col-4"><div class="border rounded p-3"><div class="text-body-secondary small">Reservations</div><strong id="count" class="fs-3 demo-stat">3</strong></div></div><div class="col-4"><div class="border rounded p-3"><div class="text-body-secondary small">Available</div><strong class="fs-3 demo-stat">8</strong></div></div></div>
<div class="row g-4"><section class="col-lg-7" aria-labelledby="list-title"><div class="d-flex align-items-center justify-content-between gap-3 mb-3"><h2 id="list-title" class="h5 m-0">Reservation list</h2><div><label for="filter" class="visually-hidden">Filter reservations by status</label><select class="form-select form-select-sm" id="filter"><option value="all">All statuses</option><option value="Reserved">Reserved</option><option value="In use">In use</option><option value="Draft">Draft</option></select></div></div><div class="table-responsive border rounded"><table class="table table-hover mb-0"><caption class="px-3">Fictional records. New entries stay in this browser tab.</caption><thead class="table-light"><tr><th scope="col">Equipment</th><th scope="col">Date</th><th scope="col">Status</th></tr></thead><tbody id="rows"><tr data-status="Reserved"><th scope="row" class="fw-medium">Camera kit A<div class="small fw-normal text-body-secondary">Mia Chen</div></th><td>10 Oct</td><td><span class="badge text-primary-emphasis bg-primary-subtle">Reserved</span></td></tr><tr data-status="In use"><th scope="row" class="fw-medium">Lighting studio<div class="small fw-normal text-body-secondary">Alex Kim</div></th><td>10 Oct</td><td><span class="badge text-success-emphasis bg-success-subtle">In use</span></td></tr><tr data-status="Draft"><th scope="row" class="fw-medium">Audio recorder<div class="small fw-normal text-body-secondary">Jules Davis</div></th><td>11 Oct</td><td><span class="badge text-secondary-emphasis bg-secondary-subtle">Draft</span></td></tr></tbody></table></div><p id="empty" class="alert alert-info mt-3" hidden>No reservations match this status.</p><p id="results" class="small text-body-secondary mt-2" aria-live="polite">3 reservations shown</p><div class="alert alert-primary mt-4 mb-0"><strong>Try the system</strong><p class="small mb-0 mt-1">Switch color mode, filter the table, submit an empty form, then review a complete reservation in a Bootstrap modal.</p></div></section>
<section class="col-lg-5" aria-labelledby="form-title"><div class="card"><div class="card-body p-3 p-md-4"><h2 id="form-title" class="h5 mb-3">New reservation</h2><form id="reservation" novalidate><div id="error-summary" class="alert alert-danger" tabindex="-1" role="alert" hidden><strong>Check the reservation details.</strong><ul class="mb-0 mt-2" id="error-links"></ul></div><div class="mb-3"><label class="form-label" for="equipment">Equipment</label><select class="form-select" id="equipment" aria-describedby="equipment-error" required><option value="">Choose equipment</option><option>Camera kit A</option><option>Lighting studio</option><option>Audio recorder</option></select><div id="equipment-error" class="invalid-feedback">Choose equipment for this reservation.</div></div><div class="mb-3"><label class="form-label" for="owner">Reserved by</label><input class="form-control" id="owner" autocomplete="name" aria-describedby="owner-hint owner-error" required><div class="form-text" id="owner-hint">Use a fictional name for this example.</div><div class="invalid-feedback" id="owner-error">Enter the name of the person reserving equipment.</div></div><div class="mb-3"><label class="form-label" for="date">Reservation date</label><input class="form-control" id="date" type="date" aria-describedby="date-error" required><div class="invalid-feedback" id="date-error">Choose a reservation date.</div></div><button type="submit" class="btn btn-primary w-100">Review reservation</button></form><p class="small text-body-secondary mt-3 mb-0">This example validates input locally. It does not reserve real equipment.</p></div></div></section></div><div id="notice" class="alert alert-success mt-4 demo-status" role="status" hidden></div></main>
<div class="modal fade" id="review-modal" tabindex="-1" aria-labelledby="review-title" aria-hidden="true"><div class="modal-dialog modal-dialog-centered"><div class="modal-content"><div class="modal-header"><h2 class="modal-title fs-5" id="review-title">Review reservation</h2><button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close review"></button></div><div class="modal-body"><dl class="row mb-0"><dt class="col-4">Equipment</dt><dd class="col-8" id="review-equipment"></dd><dt class="col-4">Reserved by</dt><dd class="col-8" id="review-owner"></dd><dt class="col-4">Date</dt><dd class="col-8" id="review-date"></dd></dl><p class="small text-body-secondary mt-3 mb-0">Confirming adds a row to this local example only.</p></div><div class="modal-footer"><button class="btn btn-outline-secondary" data-bs-dismiss="modal" type="button">Edit details</button><button class="btn btn-primary" id="confirm" type="button">Add to example</button></div></div></div></div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script><script>
const $=id=>document.getElementById(id);const fields=['equipment','owner','date'];const review=bootstrap.Modal.getOrCreateInstance($('review-modal'));
$('theme').onclick=()=>{const dark=document.documentElement.dataset.bsTheme!=='dark';document.documentElement.dataset.bsTheme=dark?'dark':'light';$('theme').setAttribute('aria-pressed',String(dark));$('theme').textContent=dark?'Light mode':'Dark mode'};
function filter(){let count=0;for(const row of $('rows').rows){row.hidden=$('filter').value!=='all'&&row.dataset.status!==$('filter').value;if(!row.hidden)count++}$('empty').hidden=count>0;$('results').textContent=count+' reservations shown'}$('filter').onchange=filter;
function validateField(id){const el=$(id),invalid=!el.checkValidity();el.classList.toggle('is-invalid',invalid);el.setAttribute('aria-invalid',String(invalid));return !invalid}
$('reservation').onsubmit=e=>{e.preventDefault();const invalid=fields.filter(id=>!validateField(id));$('error-links').replaceChildren();$('error-summary').hidden=invalid.length===0;if(invalid.length){for(const id of invalid){const li=document.createElement('li'),a=document.createElement('a');a.href='#'+id;a.className='alert-link';a.textContent=$(id+'-error').textContent;a.onclick=e=>{e.preventDefault();$(id).focus()};li.append(a);$('error-links').append(li)}$('error-summary').focus();return}for(const id of fields)$('review-'+id).textContent=$(id).value;review.show()};
for(const id of fields)$(id).addEventListener('input',()=>{if($(id).getAttribute('aria-invalid')==='true')validateField(id)});
$('review-modal').addEventListener('hidden.bs.modal',()=>$('reservation').querySelector('button').focus());
$('confirm').onclick=()=>{const row=document.createElement('tr');row.dataset.status='Reserved';const name=document.createElement('th');name.scope='row';name.className='fw-medium';name.textContent=$('equipment').value;const owner=document.createElement('div');owner.className='small fw-normal text-body-secondary';owner.textContent=$('owner').value;name.append(owner);const date=document.createElement('td');date.textContent=$('date').value;const state=document.createElement('td'),badge=document.createElement('span');badge.className='badge text-primary-emphasis bg-primary-subtle';badge.textContent='Reserved';state.append(badge);row.append(name,date,state);$('rows').prepend(row);$('count').textContent=$('rows').rows.length;$('filter').value='all';filter();review.hide();$('notice').hidden=false;$('notice').textContent='Reservation added to this local example. No data was sent.';$('reservation').reset();for(const id of fields){$(id).classList.remove('is-invalid');$(id).removeAttribute('aria-invalid')}};
</script></body></html>

Справочник по коду

  • Форма не отправляется в сервис. Подтверждённые бронирования существуют только в течение сеанса этой страницы.
  • В локальном примере используются те же закреплённые версии CSS и JavaScript; в этой копии задействованы их общедоступные URL CDN.

Метка поля, подсказка и явное состояние ошибки

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

html
<form id="reservation" novalidate>
  <label for="owner" class="form-label">Reserved by</label>
  <input id="owner" class="form-control" required
    aria-describedby="owner-hint owner-error">
  <div id="owner-hint" class="form-text">Use a fictional name.</div>
  <div id="owner-error" class="invalid-feedback">Enter a name.</div>
  <button class="btn btn-primary mt-3" type="submit">Review reservation</button>
</form>
<script>
const form = document.querySelector('#reservation');
const input = document.querySelector('#owner');
form.addEventListener('submit', event => {
  event.preventDefault();
  const invalid = !input.checkValidity();
  input.classList.toggle('is-invalid', invalid);
  input.setAttribute('aria-invalid', String(invalid));
  if (invalid) input.focus();
});
</script>

Справочник по коду

  • .is-invalid можно задавать явно, не используя .was-validated.
  • aria-describedby связывает текст подсказки и ошибки с полем; aria-invalid указывает его текущее состояние.
  • В документации предупреждается, что одной лишь пользовательской визуальной индикации ошибки недостаточно для вспомогательных технологий.

Нативное модальное окно проверки с понятной меткой

В модальном окне используются настоящий плагин Bootstrap, фон, обработка клавиши Escape и управление фокусом. Поместите заголовок в modal-header, проверяемые данные — в modal-body, а действия для продолжения — в modal-footer.

html
<button class="btn btn-primary" data-bs-toggle="modal"
  data-bs-target="#review">Review reservation</button>
<div class="modal fade" id="review" tabindex="-1"
  aria-labelledby="review-title" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h2 class="modal-title fs-5" id="review-title">Review reservation</h2>
        <button class="btn-close" data-bs-dismiss="modal"
          aria-label="Close review"></button>
      </div>
      <div class="modal-body">Camera kit A · 10 October</div>
      <div class="modal-footer">
        <button class="btn btn-outline-secondary" data-bs-dismiss="modal">Edit details</button>
      </div>
    </div>
  </div>
</div>

Справочник по коду

  • Подключите соответствующий bundle Bootstrap JavaScript один раз.
  • data API открывает статический пример; в работающей форме бронирования после успешной проверки используется Modal.getOrCreateInstance.
  • Используйте shown.bs.modal для поведения, которое должно запускаться после завершения перехода открытия.

Адаптивная композиция списка и формы

При контрольной точке lg список оборудования занимает семь столбцов, а форма — пять. Ниже lg оба раздела располагаются друг под другом. g-4 задаёт промежуток между элементами композиции в 1.5rem. Столбцы определяют ширину, а семантические разделы и заголовки описывают содержимое.

html
<main class="container py-4">
  <div class="row g-4">
    <section class="col-lg-7" aria-labelledby="reservations-title">
      <h2 id="reservations-title" class="h5">Reservations</h2>
      <div class="table-responsive">
        <table class="table table-hover">
          <caption>Fictional equipment reservations</caption>
          <thead><tr><th scope="col">Equipment</th><th scope="col">Status</th></tr></thead>
          <tbody><tr><th scope="row">Camera kit A</th><td>Reserved</td></tr></tbody>
        </table>
      </div>
    </section>
    <section class="col-lg-5" aria-labelledby="new-title">
      <h2 id="new-title" class="h5">New reservation</h2>
    </section>
  </div>
</main>

Справочник по коду

  • Эту же сетку можно настроить с col-md-*, если содержимое действительно помещается на более ранней контрольной точке.
  • Используйте приведённую выше таблицу контрольных точек, а не медиазапросы с переменными CSS: var() не может задавать порог медиазапроса.
04

Настройка AI-агента дизайн-системы Bootstrap

Отправная точка для реализации

Для этого полного примера HTML не требуется этап сборки. Он импортирует Bootstrap 5.3.8 из закреплённых URL CDN, указанных в файле. В примерах ниже отдельно показаны отдельные шаблоны из этой работающей страницы.

sh
# Save the complete index.html from Component Examples in a new folder.
# Serve that folder with Python 3:
python3 -m http.server 8000
# Open http://localhost:8000/ in a browser.

Запрос для вашего проекта

Промпт для AI-агента
Создайте интерфейс бронирования оборудования на основе Bootstrap 5.3.8 и этого руководства. Используйте строку g-4 с col-lg-7 и col-lg-5, отступы p-3 p-md-4, учитывающие тему роли цветов фона и текста для приглушённого и акцентного содержимого, семантическую таблицу и поля формы с метками. Перед открытием нативного модального окна Bootstrap Modal выполняйте проверку с явными сообщениями об ошибках и сводкой. При редактировании сохраняйте введённые данные; добавляйте записи только в локальное состояние демонстрации, если не предоставлен настоящий API. Поддерживайте светлую и тёмную темы data-bs-theme и закрытие с клавиатуры. Не заменяйте заданную шкалу произвольными значениями.
05

Дизайн-система Bootstrap: источники и область применения

Руководство по приложению Bootstrap 5.3.8 для OpenDesign и запускаемый пример с нативными компонентами. Справочные значения взяты из документации Bootstrap по ссылкам и закреплённого скомпилированного CSS. Записи о бронированиях, компоновка и сводка проверки — оригинальный код приложения; реальные бронирования не отправляются.