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 !

49 комментариев
  1. Антон:

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

    Спасибо, классно!

    Единственное замечание. Если страница большая (с вертикальной полосой прокрутки) а «кнопка», активирующая модальное окно, расположена в подвале, то при клике по ней, одновременно с открытием модального окна страница прокручивается вверх к самому началу. Можно ли сделать как-то так, что бы сама страница оставалась на месте?

    Ответить
    • driver:

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

      В селекторе .dm-overlay замените абсолютное позиционирование на фиксированное: position: fixed;

      Ответить
      • Антон:

        Ура! 🙂

        И, если можно, ещё один вопрос…

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

        Ответить
  2. Вадим:

    Действительно шикарные примеры!

    Перебрал массу других — эти лучшие.

    Кстати, замечание в прежнем комментарии также помогли с позиционированием окна.

    У меня правда не до конца правильно работает. Может подскажите как исправить.

    При нажатии на ссылку, всплывает модальное окно, с требуемым изображением и текстом, все супер, но...нет кнопки закрытия окна. Таким образом закрыть его возможно только нажав в меню браузера кнопку «Вернуться обратно» (проверял в Опере, Хроме и Лисе).

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

    Ответить
  3. Вадим:

    разобрался:

    Х

    Ответить
  4. Stas:

    Подскажите пожалуйста, как прописать чтобы Модальное окно открывалось при загрузке страницы

    Ответить
    • driver:

      Используйте js:

      <script type="text/javascript"> var delay_popup = 5000; setTimeout("document.getElementById('win1').style.display='block'", delay_popup); </script>

      В этом случае окно с идентификатором win1 будет появляться по истечению 5 секунд после загрузки страницы. ID конечно же может быть любым главное чтобы соответствовал id модального окна

      Так же, кнопке «закрыть» необходимо прописать событие onclick, иначе пользователь не сможет закрыть окно:

      <a href="#close" class="close"onclick="document.getElementById('win1').style.display='none';"></a>

      Всё! Более подробно можете прочитать у меня же на блоге, в этой статье: Тынц

      Ответить
  5. Stas:

    Радуюсь как ребенок...

    Спасибо Вам большое, все получилось и работает!

    Как у Вас все просто и оригинально, Вы не представляете, что я у себя писал и пробовал, пока вы не подсказали.

    Если не затруднит, подскажите, чтобы скролл работал под модальным окном, если это возможно.

    Большое спасибо!

    Ответить
    • driver:

      В селекторе .dm-overlay смените абсолютное позиционирование на фиксированное position: fixed;

      Затем, у меня в демо для body прописано свойство overflow: hidden;, если вы используете такую же конструкцию, просто исключите это свойство и содержание под модальным окном будет прокручиваться.

      Ответить
  6. Вадим:

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

    Ответить
    • driver:

      Смотрите в сторону идентификаторов, они должны быть разные для каждого окна id="win1", id="win2", id="win3", и т.д. в соответствии значений href="#win1", href="#win2", и т.д. ссылок активирующих модальные окна.

      Ответить
      • Вадим:

        Ты просто Бог идентификаторов! От меня — величайшая благодарность! Крепко жму руку!

        Ответить
  7. Вита:

    Все отлично, но у меня также...нет кнопки закрытия окна(

    Не пойму что зделала не так.

    Пожалуйста, подскажите как добавить кнопку закрытия окна.

    Заранее спасибо.

    Ответить
    • driver:

      Не видя пациента трудно ставить диагноз и ещё трудней его лечить))).

      Проверьте присутствует ли у вас вообще ссылка, которая выполняет роль кнопки закрытия:

      <a href="#close" class="close"></a>

      Формируется кнопка в CSS, селекторы .close и .close:after, изменения при наведении устанавливаем в .close:hover:after

      Смотрите исходники в статье или демо, всё расписано до мелочей.

      Ещё как вариант, пропишите в ссылке закрытия символ X в качестве анкора:

      <a href="#close" class="close">X</a>

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

      Ответить
  8. Артур:

    И все-таки! Как сделать, чтобы окно закрывалось при клике на темный фон? Пользователи нынче нервные — могут и ноутбук поломать.

    Ответить
    • driver:

      Ну, раз так всё серьёзно, то самое простое, это использовать событие onclick для div-контейнера с модальным окном:

      <div class="dm-overlay" id="win1" onclick="document.getElementById('win1').style.display='none';">

      остаётся только следить чтобы идентификатор соответствовал тому или иному окошку. Всё!

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

      Ответить
    • driver:

      Да, и ещё, ссылку на вызов окна, тоже придётся немного подкорректировать:

      <a href="#win1" class="btn" onclick="document.getElementById('win1').style.display='block';">Открыть окно 1</a>

      Но это уже совсем не тот «коленкор»))

      Ответить
  9. Вячеслав:

    Приветствую!

    Подскажите, что делаю не так, скопировал так как указано в материале выше.

    Задача: при нажатии на ссылку должно появляться модальное окно на весь экран с текстом.

    Результат: окно с необходимым содержимым отображается постоянно, без «Х» для закрытия.

    Заранее благодарю!

    Ответить
    • driver:

      Вячеслав, доброго времени суток!

      В статье всё разложено по полочкам, не один раз уже объяснял дополнительно, весь код с пояснениями, даже расписал в комментах вариант появления окна при загрузке сайта, хотя статья изначально совсем о другом))).

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

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

      Ответить
      • Вячеслав:

        Благодарю за такую оперативность! (like)

        насколько связанно это с решением моего вопроса даже не представляю, вы как Профи может объясните:

        Прочитав в очередной раз комменты, попробовал это X И о Чудо, все заработало )

        p.s. Блог у Вас правильный, много чего почерпнул, думаю буду сюда захаживать в гости!

        Ответить
  10. Костя:

    Замечательное решение. Просто нет слов.

    Ответить
  11. Дмитрий:

    Помогите пожалуйста! У меня есть кино сайт на движке DLE 10.2 настроен все работает но нету вкладки Трейлеры так вот я хочу сделать кнопку (Просмотреть трейлер) что бы когда на нее нажимали всплывало окно и видео с ютуба воспроизводилось. Но это не все мне нужно что бы было все просто то есть в создоном дополнительном поле мне нужно было бы вставить только ссылку на трейлер с ютуба и все. Я перепробовал кучу скриптов и модулей но они либо нарушали структуру сайта либо не работали. Не могли бы вы мне объяснить подробно как мне осуществить мою идею??

    Ответить
  12. cruxpux:

    Добрый день!

    Вставил туда галерею адаптивную

    не работает нормально ваша форма и галерея

    подскажите что нуно делать для вставки туда различных плагинов

    Ответить
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