Dobrovoi Master
сделано с душой

В состоянии постоянного подключения...
Главная » Уроки » Адаптивное модальное окно строго по центру

Адаптивное модальное окно строго по центру

Как сделать стопроцентно адаптивное на чистом CSS, которое к тому же выводилось строго по центру, и одинаково хорошо, без видимой ломки, смотрелось на различных типах экранов пользовательских устройств?

Вопрос конечно интересный, а процесс реализации и вовсе увлекательнейший. Конечно, макет модального окна, о котором сегодня пойдёт речь, скорее резиновый, так как адаптивность, в навороченных кругах, подразумевает наличие, прописных мета-тегов для мобильных устройств, медиа-запросов в css и прочие установленные «трендованными буржуинами» и еже сними, стандартами.
К теме создания модальных окон, я возвращался много раз, описывал способы с использованием jQuery и исключительно на чистом . В представленном сегодня примере объединил некоторые концепции и получилось то, что получилось. Не стоит принимать этот метод, как руководство к действию, скорее это, рабочий материал, поиски оптимальных решений.

Смотрите живой пример, а далее разберём немного по-подробнее составляющие.
 
Адаптивное модальное окно на чистом CSS

Как видите, при активации, модальное окно появляется строго по центру и не меняет своего положения при изменении размеров экрана просмотра, плавно масштабируется само окно. Для абсолютного центрирования модального блока метод с применением свойства display: table-cell;, на мой взгляд, это один из самых лучших и простых способов, о котором подробно описано в статье на 456bereastreet.com. Есть у этого решения маленький недостаток — дополнительная разметка, необходимо целых ))) три элемента. В разметке Html в итоге, получаем следующую картину:

Html разметка

<div class="dm-overlay" id="win1">
    <div class="dm-table">
        <div class="dm-cell">
            <div class="dm-modal">
                <a href="#close" class="close"></a>
                <h3>Заголовок модального окна</h3>
                <div class="pl-left">
                    <img src="http://lorempixel.com/320/320/people/some-text">
                </div>
                <p>Текстовое содержание....</p>
            </div>
        </div>
    </div>
</div>

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

<a href="#win1" class="btn">Открыть окно 1</a>

Базовым контейнером, в который размещаем модальный блок с содержанием, является слой затемнения, чаще всего я выношу фон в отдельный div, в данном же случае, решил объединить в единую конструкцию все элементы. Тесты показали, что всё работает нормально, только вот с реализацией закрытия окна по клику вне зоны блока(по слою затемнения), возникают трудности.

Весь макет состоит из четырёх div-контейнеров с последовательной вложенностью, под формирование которых выделены отдельные классы в css, при использовании миниатюр или видео, добавляется ещё один блок. Ключевые свойства отвечающие за центрирование окна, оставляем как есть, экспериментируйте с формированием, как самого модального блока, так и внутренних элементов:

CSS

/* слой затемнения */
.dm-overlay {
    position: fixed;
    top: 0;
    left: 0;
    background: rgba(0, 0, 0, 0.65);
    display: none;
    overflow: auto;
    width: 100%;
    height: 100%;
    z-index: 1000;
}
/* активируем слой затемнения и модальное окно */
.dm-overlay:target {
    display: block;
/* анимация и время задержки */
    -webkit-animation: fade .6s;
    -moz-animation: fade .6s;
    animation: fade .6s;
}
/* блочная таблица */
.dm-table {
    display: table;
    width: 100%;
    height: 100%;
}
/* ячейка блочной таблицы */
.dm-cell {
    display: table-cell;
    padding: 0 1em;
    vertical-align: middle;
    text-align: center;
}
/* модальный блок */
.dm-modal {
    display: inline-block;
    padding: 20px;
/* максимально возможная ширина */
    max-width: 50em;
    background: #607d8b;
/* внешняя тень блока */
    -webkit-box-shadow: 0px 15px 20px rgba(0, 0, 0, 0.22), 0px 19px 60px rgba(0, 0, 0, 0.3);
    -moz-box-shadow: 0px 15px 20px rgba(0, 0, 0, 0.22), 0px 19px 60px rgba(0, 0, 0, 0.3);
    box-shadow: 0px 15px 20px rgba(0, 0, 0, 0.22), 0px 19px 60px rgba(0, 0, 0, 0.3);
    color: #cfd8dc;
    text-align: left;
/* анимация и время задержки */
    -webkit-animation: fade .8s;
    -moz-animation: fade .8s;
    animation: fade .8s;
}

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

Для определения ширины модального блока, как вы видите, я использовал единицу измерения в em и установил максимальную ширину элемента max-width, так окно видоизменяется более корректно нежели при width: %;

Никаких дополнительных js-библиотек не подключал к работе, только магия CSS3. Модальный блок и слой затемнения, до поры до времени спрятал с газ долой(со страницы), с помощью display: block;. Прикрутил простенькую анимацию через @keyframes, с помощью свойства opacity, с небольшой задержкой, происходит плавный переход модального окна и слоя затемнения в открытое состояние. У кого появится желание, можете смело поэкспериментировать, благо примеров в сети предостаточно.

/* анимация при появлении затемнения и блоков с содержанием */
@-moz-keyframes fade {
    from { opacity: 0; }
to { opacity: 1 }
}
@-webkit-keyframes fade {
    from { opacity: 0; }
to { opacity: 1 } 
}
@keyframes fade {
    from { opacity: 0; }
to { opacity: 1 }
}

Часто модальные окна используют для вывода, не только текстовых сообщений и различных форм, но и для демонстрации изображений, знаменитый lightbox и т.д. Так же, в купе с текстом органично смотрятся в всплывающих окошках, встроенные в текст миниатюры картинок. Постарался предусмотреть и такой вариант применения, обозначив ряд выделенных классов в CSS, содержащих свойства формирующие вывод изображений внутри окна.
Для миниатюр определил возможность размещения, как справа, так и слева от текста, с шириной в 25%, а масштабной картинке назначил ширину в width: 100%; от родительского контейнера, тем самым обеспечив возможность пропорционального изменения, при просмотре на экранах различных пользовательских устройств. О том как сделать картинки адаптивными, подробно рассказывал ранее, именно этот метод и использовал.
 
Адаптивные изображения в модальном окне

/* изображения в модальном окне */
.dm-modal img {
    width: 100%;
    height: auto;
}
/* миниатюры изображений */
.pl-left,.pl-right {
    width: 25%;
    height: auto;
}
.pl-right {
    float: right;
    margin: 5px 0 5px 15px;
}
.pl-left {
    float: left;
    margin: 5px 15px 5px 0;
}

Так и не найдя корректного, всех и вся удовлетворяющего способа остановки проигрывания видео при закрытии модального окна, собранного и работающего на CSS3, всё же включил в пример и вариант всплывающего блока с адаптивным видео. Решения по выключению видеоролика не то чтобы нет, есть, но оно не совсем кошерное, многих перекрученных веб-дел мастеров, просто переворачивает от использования пустующего атрибута href="" в ссылке кнопки закрытия. Это и понятно, в таком случае видео останавливается посредством перезагрузки страницы, что не есть хорошо.
Видеоролики можете использовать как свои, размещённые у себя на сервере, так и с любого видеосервиса, предлагающего различные методы вставки видео на сайт через iframe, object или embed. Подробно о модальном блоке видео на css3, мы рассматривали ранее, в отдельном уроке, кому интересно, можете освежить память.

/*видео в модальном окне*/
.video { 
  position: relative; 
  padding-bottom: 56.25%; 
  height: 0; 
  overflow:hidden; 
} 
.video iframe, 
.video object, 
.video embed {
  position: absolute; 
  top: 0; 
  left: 0; 
  width: 100%;
  height: 100%; 
}

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

/* Стили модального окна и содержания 
-------------------------------------------------------------------------------*/
 
/* слой затемнения */
 
.dm-overlay {
    position: fixed;
    top: 0;
    left: 0;
    background: rgba(0, 0, 0, 0.65);
    display: none;
    overflow: auto;
    width: 100%;
    height: 100%;
    z-index: 1000;
}
/* активируем модальное окно */
 
.dm-overlay:target {
    display: block;
    -webkit-animation: fade .6s;
    -moz-animation: fade .6s;
    animation: fade .6s;
}
/* блочная таблица */
 
.dm-table {
    display: table;
    width: 100%;
    height: 100%;
}
/* ячейка блочной таблицы */
 
.dm-cell {
    display: table-cell;
    padding: 0 1em;
    vertical-align: middle;
    text-align: center;
}
/* модальный блок */
 
.dm-modal {
    display: inline-block;
    padding: 20px;
    max-width: 50em;
    background: #607d8b;
    -webkit-box-shadow: 0px 15px 20px rgba(0, 0, 0, 0.22), 0px 19px 60px rgba(0, 0, 0, 0.3);
    -moz-box-shadow: 0px 15px 20px rgba(0, 0, 0, 0.22), 0px 19px 60px rgba(0, 0, 0, 0.3);
    box-shadow: 0px 15px 20px rgba(0, 0, 0, 0.22), 0px 19px 60px rgba(0, 0, 0, 0.3);
    color: #cfd8dc;
    text-align: left;
}
/* изображения в модальном окне */
 
.dm-modal img {
    width: 100%;
    height: auto;
}
/* миниатюры изображений */
 
.pl-left,
.pl-right {
    width: 25%;
    height: auto;
}
/* миниатюра справа */
 
.pl-right {
    float: right;
    margin: 5px 0 5px 15px;
}
/* миниатюра слева */
 
.pl-left {
    float: left;
    margin: 5px 15px 5px 0;
}
/* встраиваемое видео в модальном окне */
 
.video {
    position: relative;
    overflow: hidden;
    padding-bottom: 56.25%;
    height: 0;
}
.video iframe,
.video object,
.video embed {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
/* рисуем кнопарь закрытия */
 
.close {
    z-index: 9999;
    float: right;
    width: 30px;
    height: 30px;
    color: #cfd8dc;
    text-align: center;
    text-decoration: none;
    line-height: 26px;
    cursor: pointer;
}
.close:after {
    display: block;
    border: 2px solid #cfd8dc;
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;
    content: 'X';
    -webkit-transition: all 0.6s;
    -moz-transition: all 0.6s;
    transition: all 0.6s;
    -webkit-transform: scale(0.85);
    -moz-transform: scale(0.85);
    -ms-transform: scale(0.85);
    transform: scale(0.85);
}
/* кнопка закрытия при наведении */
 
.close:hover:after {
    border-color: #fff;
    color: #fff;
    -webkit-transform: scale(1);
    -moz-transform: scale(1);
    -ms-transform: scale(1);
    transform: scale(1);
}
/* варианты фонвой заливки модального блока */
 
.green {
    background: #388e3c!important;
}
.cyan {
    background: #0097a7!important;
}
.teal {
    background: #00796b!important;
}
/* движуха при появлении блоков с содержанием */
 
@-moz-keyframes fade {
    from {
        opacity: 0;
    }
    to {
        opacity: 1
    }
}
@-webkit-keyframes fade {
    from {
        opacity: 0;
    }
    to {
        opacity: 1
    }
}
@keyframes fade {
    from {
        opacity: 0;
    }
    to {
        opacity: 1
    }
}

На этом всё. Не буду утверждать, что всё без ошибок, тестировал во многих браузерах, про IE8 и ниже, сразу надо забыть, это что касается модального окна, центрирование и адаптивность элементов кроссбраузерные, вёрстка не едет при большом количестве текста в блоке, высота изменяемая.
Если что-то пропустил или же обнаружится ошибка, пишите в комментариях. Исходники упаковал в архив и выложил в облако на Яндекс, при возникшем вдруг желании, всегда можете их скачать.

С Уважением, Андрей .

Буду всем признателен, если поддержите проект — добавив блог в исключения AdBlock и поделитесь ссылкой на запись в своих соц-сетях:

Вы можете оставить отзыв, подписаться на обновленияОбновления блога по RSSRSS или Обновления блога на TwitterTwitter !

55 комментариев
  1. Александр:

    Добрый вечер!

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

    Но столкнулся с проблемой, в окне пытаюсь вывести iframe со своей страницей. На странице ссылки на похожие записи. При клике по ссылке пользователь переходит на 2 страницу target="_blank. Не подскажите, как закрыть попап окно через время на 1 странице?

    Спасибо!

    Ответить
  2. Ольга:

    Добрый день, в примере у Вас на сайте, четвертое окно с видео, при закрытии окна — видео перестает воспроизводится. В исходниках, которые предлагается скачать, при закрытии окна видео продолжает воспроизводится. Что нужно добавить, чтобы корректно работало?

    Ответить
    • driver:

      Вечер добрый.

      В примере ссылка кнопки закрытия прописана с пустым адресом, что вызывает перезагрузку страницы и соответственно остановку видео, в исходниках в адресе прописано #close, окно закрывается, но видео продолжает играть

      По настоящему валидного решения остановки видео средствами css, без js нет, приходится искать варианты. Например в других своих работах по модальным окнам на css3, нередко использую в адрес страницы где прописано модальное окно с видео:

      <a class="close" title="Закрыть" href="index.html"></a>

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

      Ответить
      • Ольга:

        Да, поправила код, все работает, но если видеогалерея большая, как у меня, перезагрузка страницы при просмотре каждого видео, наверно, не очень хорошо. Нет ли возможности добавить маленький скрипт для закрытия окна? Я понимаю, что чистый CSS, но может быть как вариант?

        Ответить
  3. Виктор:

    У вас в демке код прекрасен, но при использовании на своем сайте — возникает куча проблем. При открытии/закрытии окнв к ссылке добавляется #id и происходит скрол вверх страницы. Еще scc стили добавляют тегу body overflow:hidden, из за чего сайт не скролится и отображается только в первом экране, еще body добавляется line-height и что то еще, после чего дизайн просто едет.

    Ответить
    • Виктор:

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

      Ответить
  4. Я так и не понял из коментов. Как этот вариант модального окна можно использовать на сайте, когда вы добавляете

    html,

    body {

    overflow: hidden;

    }

    ???

    Ответить
    • driver:

      Понятно, что при overflow: hidden; для body, будет проблематично)) Не нужно смотреть на весь фарш демо-страницы, стили базовых элементов (html,body) исключительно для демо, просто не используйте это свойство, или же пропишите значениеauto, .dm-overlay зафиксируйте. Про скролинг и варианты позиционирования, отвечал ранее в комментах.

      Ответить
  5. Мне кажется нужно сразу писать так

    .dm-overlay {/* слой затемнения */

    position:fixed;

    z-index:1000;

    overflow:auto;

    top: 0;

    left: 0;

    display: none;

    overflow: auto;

    width: 100%;

    height: 100%;

    background: rgba (0, 0, 0, 0.65);

    }

    Это подойдет для 99% пользователей.

    Ответить
    • driver:

      Алексей, полностью с вами согласен.

      Спасибо за дополнение.

      Ответить
  6. Александр:

    В ie работать не будет...

    Ответить
    • driver:

      Спасибо что просветили, а то всё гадаю будет или не будет))) В 10,11 и Edge, всё работает прекрасно, в 9-й версии отсутствует лишь анимация, ну а на 8 и ниже пора бы уже подзабить...

      Ответить
  7. Hellion:

    Добрый день. Подскажите пожалуйста. Я из комментариев взял метод который скрывает модальное окно если нажать в любом месте а не только на крестик. Проблема в том что модальное окно закрывается даже если нажать в нем самом. В моем случае в модальном окне форма. Нажимаю на input что бы ввести телефон и модальное окно пропадает((( Подскажите пожалуйста как исправить данную проблему? Заранее крайне благодарен за ответ.

    Ответить
    • gmenjk95:

      Можно сделать несколько иначе

      Внутри блока dm-modal рядом с блоком wrap вставляешь

      И для него добавляешь стили

      .close_1 {

      position: absolute;

      width: 100%;

      height: 100%;

      top: 0;

      display: block;

      left: 0;

      }

      Ответить
  8. Роман:

    Здравствуйте,

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

    Я пока что новичок, подскажите, возможно это можно убрать js, а именно Ajax? Тогда уберу позже, когда изучу js)))

    Ответить
    • driver:

      Здравствуйте.

      В моей демке, такого косяка не просматривается, по крайней мере, я не замечал.

      Могу предположить, что баг связан с анимацией. Чтобы проверить исключите свойства анимации из селектора .dm-overlay:target, просто закомментируйте:

      /* -webkit-animation: fade .6s; -moz-animation: fade .6s; animation: fade .6s; */

      Хотя мало вероятно, что дело именно в анимации, если так, то будем глубже копать.

      Ответить
      • Роман:

        Гораздо лучше)) Спасибо огромное)))

        Правда блики идут небольшие)) Может ещё что-нибудь можно сделать?

        Ответить
  9. Ирина Чичиканова:

    Здравствуйте, Андрей! Просто счастье, что я нашла Ваш сайт, три дня билась с модальным окном, и спасение нашла только тут:) А вопрос был серьезный, могла подвести людей. Огромное спасибо Вам за множество полезностей!

    С Наступающим Новым Годом! Я желаю Вам счастья!

    Ответить
  10. Это лучшее из того, что я посмотрел в Топе Яндекса по выдаче «адаптивные модальные окна». Особый респект за комменты в CSS, поскольку чаще всего именно там непонятно. Побольше бы таких, как Вы и мир станет бесплатным)))

    Ответить
  11. Руслан:

    То, что доктор прописал! Спасибо за труды!

    Ответить
  12. В CSS сделал всплывающее окошко. Активируется по клику на ссылку. Деактивируется по клику.

    Вот после клика, страничка убегает вверх.

    Как сделать, что бы после display: none; страничка не позиционировалась вверх?

    CSS:

    #main01 {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
           }
     #popup01 {
            width: 814px;
            height: 576px;
            text-align: center;
            padding: 15px;
            border: 1px solid #0000cc;
            border-radius: 10px;
            color: #0000cc;
            position: relative;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            margin: auto;
            background: #f2f2f2;
            /*overflow: auto;*/
          }
          #main01:target {display: block; pointer-events: auto;}

    HTML:

    <a href="#main01" rel="nofollow">ссылка</a>

    <a href="#" rel="nofollow"> </a>

    P.S. onclick="return false" — не предлагать.

    Ответить
    • driver:

      Используйте <a href="#close">Закрыть</a> например, главное не одиночный слеш #, с точки зрения валидности не совсем кошерно конечно, но это уже частности.

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

      Данная же статья, больше направлена на стиль оформления и позиционирование модального окна, что явно следует из заголовка, ну, а принципы работы вторичны.

      Ответить
«12
Присоединяйтесь к обсуждению!

Отправляя кoммeнтapий, Вы автоматически принимаете правила кoммeнтиpoвaния на этом блоге.

Правила кoммeнтиpoвaния на блоге Dobrovoimaster:

  1. Во избежание захламления спамом, первый кoммeнтapий всегда проходит премодерацию.
  2. В поле "Ваш сайт" лучше указывать ссылку на главную страницу вашего сайта/блога. Ссылки на прочую веб-лабуду (в том числе блоги/сплоги, созданные не для людей) будут удалены.
  3. Не используйте в качестве имени комментатора слоганы/названия сайтов, рекламные фразы, ключевые и т.п. слова. В случае несоблюдения этого условия, имя изменяю на свое усмотрение. Просьба указывать нормальное имя или ник.
  4. Скорее всего, что не информативный и короткий кoммeнтapий вида "Спасибо!", "Интересная статья", будет удален. Исключение составляют знакомые автору блога комментаторы.
  5. Комментарии не по теме безжалостно удаляются.

Подписаться без комментирования

Обновления комментариев по RSS RSS комментариев к этой записи »

Рейтинг@Mail.ru