Используйте Bootstrap 5.3.8 и его реальную шкалу отступов, семантические цвета, адаптивную сетку и API компонентов. Проверьте работающую форму бронирования, сводку ошибок, фильтр таблицы, модальное окно и переключатель цветовой схемы, а затем используйте приведённый код.
Нативные Bootstrap 5.3.8 CSS и JavaScript, загружаемые локально. Данные о бронировании и поведение приложения приведены только в качестве примера. · Справочник по реализации
02
Справочник по дизайну системы дизайн-система Bootstrap
Скомпилированные значения Bootstrap 5.3.8 по умолчанию CSS и документация версии 5.3. Значения приведены по умолчанию и не являются обязательными правилами бренда. Сравнение rem с пикселями предполагает корневой размер шрифта 16px; на меньших экранах адаптивные размеры шрифта могут отличаться от значений для больших экранов. У окружающей страницы OpenDesign остаётся собственная типографика.
Дизайн-система Bootstrap: выберите CSS и обязанности JavaScript для Bootstrap
Одна таблица стилей, поведение компонентов — по желанию
Скомпилированная таблица стилей Bootstrap предоставляет сетку, типографику, утилиты и оформление компонентов. Пакет JavaScript добавляет интерактивные плагины, например Modal, Collapse и Dropdown. Для стилизованной кнопки JavaScript не нужен, а для запуска модального окна через data-bs-toggle — нужен. В рабочем предварительном просмотре локально загружаются соответствующие таблица стилей и пакет версии 5.3.8, чтобы элементы управления демонстрировали реальные принципы их работы.
Фильтрация таблицы бронирований, сводка ошибок и локальное добавление строк реализованы в коде приложения. Такое разделение позволяет заменить вымышленные записи данными сервиса, не приписывая логику бронирования самому Bootstrap.
CSS: макет, типографика, кнопки, поля, таблицы и оформление состояний.
Bootstrap JavaScript: открытие модального окна, фон-затемнение, реакция на Escape и управление фокусом.
JavaScript приложения: сообщения проверки, фильтрация записей и локальное обновление данных.
Выберите скомпилированный CSS для быстрого старта или продукта, в котором можно использовать стандартный набор утилит. Исходный код Sass подойдёт, если нужно изменить карты темы, генерацию утилит или сетку на этапе сборки. Пользовательские свойства CSS во время выполнения подходят для настройки отдельных компонентов, но изменение корневой цветовой переменной не пересобирает все заранее скомпилированные варианты.
Дизайн-система Bootstrap: семантические цвета и цветовые режимы
Сочетайте поверхность статуса с соответствующим цветом текста
Для значков бронирования используются bg-primary-subtle и text-primary-emphasis. Это парные семантические роли: цвет текста и фон адаптируются при изменении data-bs-theme. Однотонный синий фон в сочетании с произвольным серым текстом лишает их этой связи. Кроме того, статусы «Забронировано», «Используется» и «Черновик» по-прежнему обозначены текстом: цвет — не единственный способ передать их смысл.
Для отдельного пользовательского действия переопределите локальные свойства --bs-btn-*. Задайте значения не только для обычного фона, но и для состояний hover и active. Пример ниже показывает вариант для приложения, а не значение по умолчанию в Bootstrap. Применяйте этот класс только к нужной кнопке, чтобы он случайно не повлиял на все основные действия в другой части страницы.
Разделяйте семантику документа и визуальный размер
Главный заголовок предварительного просмотра — элемент h1 с классом h3: он остаётся основным заголовком страницы, но использует меньший визуальный размер, подходящий для инструмента. Заголовки разделов — элементы h2 со стилем h5. Bootstrap предоставляет стили как для самих элементов, так и для соответствующих классов заголовков, позволяя разделить семантику и оформление без пропуска уровней в структуре документа.
Размер основного текста по умолчанию — 1rem, высота строки — 1.5. Размеры от h1 до h4 адаптивно увеличиваются и достигают значений из справочной таблицы. Поэтому снимок экрана при одной ширине не отражает всю шкалу типографики. Используйте скомпилированные стили или описанное поведение Sass, а не копируйте размер в пикселях, измеренный в одном окне просмотра.
Назначьте вторичному тексту роль, адаптирующуюся к теме
text-body-secondary зависит от цветового режима основного текста. Этот стиль подходит для дополнительной информации о записи, например имени владельца под названием оборудования. Класс small уменьшает текст относительно окружающего, поэтому его не следует применять ко всем подписям полей: форму станет сложнее быстро просматривать. Оставляйте подписи в стандартном размере формы, а компактный текст используйте для подсказок и метаданных.
Дизайн-система Bootstrap: создавайте макеты с помощью утилит отступов и сетки
Используйте шкалу вместо произвольных интервалов
p-3 задаёт внутренний отступ 1rem, p-4 — 1.5rem, а p-5 увеличивает его до 3rem. Обозначения — это ключи шкалы, а не значения в пикселях. В примере используется p-3 p-md-4: при ширине 768px внешний внутренний отступ увеличивается, а mb-3 разделяет группы полей интервалом 1rem. Это правило относится к данному примеру и не создаёт новую официальную шкалу отступов.
Дизайн-система Bootstrap: создавайте поля с явными связями
Свяжите подписи, подсказки и сообщения об ошибках
form-label оформляет настоящую метку; её значение for должно совпадать с id поля ввода. form-control оформляет текстовые поля ввода, а form-select — список выбора. В примере aria-describedby связывает поле с подсказкой и сообщением об ошибке, а required задаёт реальное ограничение. Имена классов сами по себе не создают эти семантические связи.
Используйте настоящее состояние ошибки и доступную сводку
При отправке примера проверяется каждое поле, задаются is-invalid и aria-invalid, создаются текстовые ссылки на поля с ошибками, а фокус переводится на сводку. Исправление поля обновляет его состояние, не удаляя другие ответы. Этот прикладной слой необходим: в документации Bootstrap предупреждается, что одни лишь пользовательские визуальные подсказки не полностью доступны вспомогательным технологиям.
Перед тем как отметить поле как ошибочное, проверьте результат фактической проверки ограничений.
Свяжите текст ошибки с полем и сообщите о его недопустимом состоянии.
После отправки переместите фокус на полезную сводку или первое поле с ошибкой.
Дизайн-система Bootstrap: показывайте записи и фильтруйте их, сохраняя смысл
Используйте компонент таблицы для сопоставимых данных
В таблице есть заголовки столбцов и строк, а также подпись. table-hover добавляет подсветку при наведении, но не превращает строки в кнопки. Фильтрация скрывает подходящие строки и обновляет число результатов в области aria-live. Статус показан текстом внутри бейджа, поэтому его смысл сохраняется при смене цветового режима.
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 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 и настоящий результат проверки. В примере страницы для трёх полей предусмотрена сводка ошибок со ссылками, на которые можно перевести фокус. Одной красной рамки недостаточно, чтобы сообщить, что нужно исправить.
.is-invalid можно задавать явно, не используя .was-validated.
aria-describedby связывает текст подсказки и ошибки с полем; aria-invalid указывает его текущее состояние.
В документации предупреждается, что одной лишь пользовательской визуальной индикации ошибки недостаточно для вспомогательных технологий.
Нативное модальное окно проверки с понятной меткой
В модальном окне используются настоящий плагин Bootstrap, фон, обработка клавиши Escape и управление фокусом. Поместите заголовок в modal-header, проверяемые данные — в modal-body, а действия для продолжения — в modal-footer.
Подключите соответствующий bundle Bootstrap JavaScript один раз.
data API открывает статический пример; в работающей форме бронирования после успешной проверки используется Modal.getOrCreateInstance.
Используйте shown.bs.modal для поведения, которое должно запускаться после завершения перехода открытия.
Адаптивная композиция списка и формы
При контрольной точке lg список оборудования занимает семь столбцов, а форма — пять. Ниже lg оба раздела располагаются друг под другом. g-4 задаёт промежуток между элементами композиции в 1.5rem. Столбцы определяют ширину, а семантические разделы и заголовки описывают содержимое.
Эту же сетку можно настроить с 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. Записи о бронированиях, компоновка и сводка проверки — оригинальный код приложения; реальные бронирования не отправляются.