Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Модальное окно и выпадающее меню

Модальное окно (modal) появляется поверх страницы и затемняет всё остальное: подтвердить удаление, заполнить короткую форму. Выпадающее меню (dropdown) раскрывает список действий под кнопкой. Bulma рисует оба элемента, но открывать и закрывать их должен ваш JavaScript: элемент виден, только пока у него есть класс is-active.

Модальное окно

Окно состоит из трёх частей: затемнение modal-background, содержимое modal-content и кнопка-крестик modal-close. Разметку кладут в конец <body>:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.4/css/bulma.min.css">
 
<div style="min-height: 260px">
  <button class="button is-danger js-open" data-target="cancel-modal">Отменить заказ</button>
</div>
 
<div class="modal" id="cancel-modal">
  <div class="modal-background"></div>
  <div class="modal-content">
    <div class="box">
      <p class="title is-5">Отменить заказ №1042?</p>
      <p class="mb-4">Гость получит уведомление об отмене.</p>
      <div class="buttons">
        <button class="button is-danger">Да, отменить</button>
        <button class="button js-close">Нет</button>
      </div>
    </div>
  </div>
  <button class="modal-close is-large" aria-label="Закрыть"></button>
</div>
 
<script>
  const openModal = (modal) => modal.classList.add('is-active');
  const closeModal = (modal) => modal.classList.remove('is-active');
 
  document.querySelectorAll('.js-open').forEach((button) => {
    const modal = document.getElementById(button.dataset.target);
    button.addEventListener('click', () => openModal(modal));
  });
 
  document.querySelectorAll('.modal-background, .modal-close, .js-close').forEach((el) => {
    el.addEventListener('click', () => closeModal(el.closest('.modal')));
  });
 
  document.addEventListener('keydown', (event) => {
    if (event.key === 'Escape') {
      document.querySelectorAll('.modal.is-active').forEach(closeModal);
    }
  });
</script>

Нажмите красную кнопку: фон затемнится, по центру появится белое окно с вопросом. Закрывают его крестик, кнопка «Нет», щелчок по затемнению и клавиша Escape — каждое из этого скрипт обрабатывает отдельно. Блок с min-height нужен только чтобы окну хватило высоты в превью.

Окно-карточка

Для окна с шапкой и кнопками внизу вместо modal-content используют modal-card:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.4/css/bulma.min.css">
 
<div style="min-height: 300px"></div>
 
<div class="modal is-active">
  <div class="modal-background"></div>
  <div class="modal-card">
    <header class="modal-card-head">
      <p class="modal-card-title">Новое блюдо</p>
      <button class="delete js-close" aria-label="Закрыть"></button>
    </header>
    <section class="modal-card-body">Здесь форма с названием и ценой.</section>
    <footer class="modal-card-foot">
      <div class="buttons">
        <button class="button is-success">Сохранить</button>
        <button class="button js-close">Отмена</button>
      </div>
    </footer>
  </div>
</div>

Окно с серой шапкой, белым телом и кнопками внизу. Чтобы его было видно в превью сразу, у modal уже стоит is-active; в проекте этот класс ставит скрипт из примера выше. Кнопку modal-close здесь не используют: окно закрывают крестик delete в шапке и «Отмена», а их класс js-close уже есть в списке селекторов того скрипта.

Выпадающее меню

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.4/css/bulma.min.css">
 
<div style="min-height: 180px">
  <div class="dropdown" id="order-actions">
    <div class="dropdown-trigger">
      <button class="button" aria-haspopup="true" aria-controls="order-menu">Действия ▾</button>
    </div>
    <div class="dropdown-menu" id="order-menu" role="menu">
      <div class="dropdown-content">
        <a href="#" class="dropdown-item">Распечатать чек</a>
        <a href="#" class="dropdown-item">Изменить</a>
        <hr class="dropdown-divider">
        <a href="#" class="dropdown-item has-text-danger">Удалить</a>
      </div>
    </div>
  </div>
</div>
 
<script>
  const dropdown = document.getElementById('order-actions');
  dropdown.querySelector('.dropdown-trigger button').addEventListener('click', (event) => {
    event.stopPropagation();
    dropdown.classList.toggle('is-active');
  });
  document.addEventListener('click', () => dropdown.classList.remove('is-active'));
</script>

Нажмите «Действия» — под кнопкой откроется белый список из трёх пунктов. Щелчок в любом другом месте страницы закрывает его: stopPropagation не даёт клику по кнопке сразу же дойти до document.

Без JavaScript

Если меню достаточно открывать при наведении мыши, скрипт не нужен: добавьте dropdown модификатор is-hoverable. Но на телефоне наведения нет, поэтому для мобильных сайтов надёжнее вариант с кликом. Модификаторы is-right и is-up выравнивают меню по правому краю или открывают его вверх.

Частая ошибка

Положить модальное окно внутрь карточки или колонки. Если у родителя есть transform или overflow: hidden, окно может обрезаться или встать не по центру экрана. Разметку modal держите прямо в <body>, в конце страницы.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.