Статьи

Модные модальные окна без JavaScript

То, что мы собираемся сделать, это модальное окно, которое открывается в центре экрана при нажатии на ссылку, в то время как все, что лежит в основе окна, становится размытым. Это можно сделать с помощью элемента ` Dialog` , но в настоящее время нам не нужен JavaScript для решения этой задачи. Ну, есть два основных метода обработки событий onClick в CSS — checkbox-hack и selection by: target. Второй способ привязывает наше модальное окно к хешу URL. Таким образом, вы можете обратиться к модальному окну в URL, что довольно удобно. Крис Койер привел пример выделения текста в соответствии с целевым состоянием на http://css-tricks.com/on-target/. Он также отметил побочный эффект «прыжка» и предложил исправление JavaScript. Ян Ханссоноднако сделал пример виджета со вкладками контента, фиксирующего эффект путем установки целевых якорей в фиксированном положении. Вот и все. Давайте напишем теперь наш пример HTML. Сначала нам нужны якоря, чтобы сохранить состояние хэша URL. Один — открыть модальное окно (id = about), а второй — закрыть все окна (id = start). Поскольку нам не нужны реальные ссылки, мы можем сделать якоря некоторых нейтральных элементов, например span.

<span id="start" class="target"><!-- Hidden anchor to close all modals --></span>
<span id="about" class="target"><!-- Hidden anchor to open adjesting modal container--></span>

Далее мы помечаем модальное окно:

<div class="modal">
    <div class="content vertical-align-middle">
    <h2>About</h2>
    <article>Lorem ipsum</article>
      <a class="close-btn" href="#start">X</a>
    </div>
</div>

И чтобы показать, что модальное окно действительно размывает подстилающий контент, мы помещаем фиктивную страницу HTML в контейнер (`.page-container`) ниже:

<div class="page-container">
  <h1>Lorem ipsum dolor sit amet,</h1>
  <p><a href="#about">Open Modal Window</a> Lorem ipsum dolor sit amet.../p>
</div>

Мы прячем наши якоря и устанавливаем их в фиксированное положение, как предложил Ян Ханссон.

.target {
  display: block;
  left: 0;
  position: fixed;
  top: 0;
  width: 0;
  height: 0;
  visibility: hidden;
  pointer-events: none;
 }

Затем мы расширяем контейнер модального окна, чтобы заполнить все видимые области просмотра.

.modal {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  z-index: 100;
  text-align: center;
  display: none;
  /* Fallback for legacy browsers */
  background-color: rgba(0,0,0,0.6);
}

Обратите внимание, что z-index, как ожидается, будет выше, чем любой в .page-container. Нам нужна модальная коробка прямо в центре экрана. Поскольку его высота изначально неизвестна, мы используем трюк с «вертикальным центрированием» .

.modal::before {
  content: '';
  display: inline-block;
  height: 100%;
  vertical-align: middle;
  margin: 0;
}
.modal > .content {
   text-align: left;
   display: inline-block;
   background-color: #b13e12;
   box-sizing: border-box;
   color: white;
   position: relative;
   width: 500px;
   padding: 20px;
 }

Как вы, наверное, заметили, изначально модальное окно контейнера скрыто. Мы должны показать это, когда хеш URL совпадает с привязкой к ближайшему соседу (.target).

/* Behaviour on legacy browsers */
.target:target + .modal {
    display: block;
}

Это открытие не выглядит нарядно. Но мы можем улучшить UX в современных браузерах:

:root .modal {
  display: block;
  transition: transform 0.3s cubic-bezier(0.5, -0.5, 0.5, 1.5);
  transform-origin: center center;
  transform: scale(0, 0);
  background-color: transparent;
}
:root .modal > .content {
  box-shadow: 0 5px 20px rgba(0,0,0,0.5);
}
:root .target:target + .modal {
  transform: scale(1, 1);
}

Устаревшие браузеры, не поддерживающие CSS3, будут игнорировать любые стили с префиксом: root и, следовательно, будут отображать окно без этих эффектов.

Как насчет размытия содержимого страницы, лежащего в основе окна? Мы применим фильтр размытия к .page-container, когда идентификатор любого модального окна (кроме #start) совпадает с хешем URL.

:root .target:target ~ .page-container {
   filter: blur(5px);
  -webkit-filter: blur(5px);
  filter: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' ><filter id='blur5'><feGaussianBlur in='SourceGraphic' stdDeviation='5' ></feGaussianBlur></filter></svg>#blur5"); // for Firefox
  filter:progid:DXImageTransform.Microsoft.Blur(PixelRadius='5');
}
:root span[id="start"]:target ~ .page-container {
 filter: none;
 -webkit-filter: none;
}

Вот что мы получаем:

Смотрите модное окно Pen Fancy без JavaScript от Дмитрия Шейко ( @dsheiko ) на CodePen .

Улучшение для лучшего пользовательского опыта

Возможно, вам не хватает некоторых дополнительных функций, таких как закрытие модов при нажатии Esc или клик за пределами модального содержимого. Мы можем внести это с помощью небольшого количества JavaScript:

Посмотрите Модное окно Pen Fancy с небольшим количеством JavaScript от Дмитрия Шейко ( @dsheiko ) на CodePen .

Откат для IE8

: псевдо-селектор target имеет хорошую поддержку среди современных браузеров, но, как вы можете догадаться, он не поддерживается в браузерах IE с версиями меньше 9. Тем не менее, мы можем изменить это поведение, используя некоторый JavaScript:

(function( window ){
 
  var doc = window.document,
      /**
       * Remove .is-expanded from all modals and add it to the target
       * @returns {void}
       */
      shimTargetOnModals  = function() {
        var i = 0,
            len,
            id = window.location.hash.substr( 1 ),
            nextSibling = doc.querySelector( "#" + id + " + .modal" ),
            nodeList = doc.querySelectorAll( ".target + .modal" ),
            len = nodeList.length;
 
        // Close all other modals
        for ( ; i < len ; i++ ) {
          nodeList[ i ].className = "modal";
        }
        // Expand requested window
        if ( nextSibling ) {
          nextSibling.className = "modal is-expanded";
        }
      };
 
  window.attachEvent( "onload", function(){
    window.attachEvent( "onhashchange", shimTargetOnModals );
    shimTargetOnModals();
  });
 
 
}( window ));

Требуются некоторые дополнительные стили:

.modal.is-expanded {
   display: block;
}
.modal.is-expanded > .content {
  top: 50%;
  margin-top: -45px;
}