Учимся делать веб-сайты с нуля до трудоустройства. Разбираемся, как делать дизайн и верстку. Сегодня разберемся, как делать диалоговые окна, работать с кнопками и формами.
Те, кто хочет индивидуальное обучение с преподавателем и быстрое гарантированное трудоустройство, пишите нам в телеграм:
Что было на прошлом занятии?
Мы научились делать адаптивную верстку. Сделали так, чтобы сайт работал везде.
Вот ссылка на архив с результатами прошлого урока:
https://github.com/madmaker/srmt-lsn11/archive/refs/tags/v1.zip
Скачайте себе этот архив, распакуйте и откройте в vsCode. На его основе мы будем делать этот урок.
Что будет на этом уроке?
На этом уроке мы научимся делать:
- Диалоговые окна
- Контактные формы
Если в процессе изучения что-то не понятно - не стесняйтесь спрашивать нас и других учеников в нашей открытой группе в телеграм:
Для тех, кто только к нам присоединился, ссылка на все уроки:
И ссылка на самый первый урок:
Пишем код диалогового окна
Для начала скачайте код результатов предыдущего занятия, распакуйте и откройте в vscode. Это занятие будет на основе предыдущего. Ссылка на код:
https://github.com/madmaker/srmt-lsn11/archive/refs/tags/v1.zip
Мы хотим получить вот такое диалоговое окно. Какое оно:
- На весь экран
- С подложкой с темным фоном
- Поверх всех остальных элементов
- Имеет свой фон
- Имеет внутри текст
- Имеет внутри контактную форму
- В углу крестик, при клике на который окно должно закрываться
- На нажатие кнопки ESC окно должно закрываться
- При клике на подложку окно должно закрываться
- При клике на кнопку "Поехали" форма должна проверяться и отправляться (это рассмотрим на следующем уроке)
- Должно загружаться асинхронно: то есть не сразу со всей страницей, а после окончания загрузки или когда пользователь нажмет на кнопку (рассмотрим на следующих уроках)
Код диалога не должен грузиться перед остальным сайтом, поэтому диалоговое окно мы будем описывать сразу под закрывающим тэгом footer. Сразу для всех диалогов сделаем общий контейнер <aside>, тем самым обозначим, что это по смыслу контент не имеющий большой важности. Это уже элементы взаимодействия с пользователем.
Внутри <aside> сделаем контейнер <div></div> для нашего диалога. Определимся, что для всех диалогов будет общий класс "modal". (Modal - потому что это модальное окно. Модальное - потому что оно поверх всех остальных и перекрывает взаимодействие с сайтом, пока его не закрыть).
Я дальше буду код вписывать скринами, чтобы вы сами его писали, а не копировали.
Наш новый контент появился в браузере в самом низу, как мы и заказывали.
Описываем стили для модального окна
Теперь работаем со стилями.
Давайте сразу сделаем новый фрагмент scss _modals.scss и импортируем его в genereal.scss
Запускаем SASS Watcher
Уже привычное по прошлым урокам действие: открываем новый терминал в vscode и запускаем watcher (вотчер), чтобы наш scss автоматически компилировался в css:
sass --watch scss:css
Обернем html-код контента окна еще в один контейнер: <div class="modal-content"> - в нем будет контент окна.
В _modal.scss добавляем код:
.modal {
position: fixed;
z-index: 500;
top:0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.8);
display: grid;
grid-template-columns: 1fr;
align-items: center;
.modal-content {
background-color: black;
background-image: url('../img/businessman-giving-hand-shake-2.jpg');
background-position: center;
background-size: cover;
width:400px;
margin: 0 auto;
}
}
Результат будет такой:
Теперь подробнее о стилях.
position: fixed;
Определяем тип позиционирования елемента. Далее нужно будет задать координаты left, top, bottom, right. А вот относительно чего координаты, position как раз и задает:
- fixed - Фиксированный относительно окна. Задаем координаты относительно краев окна браузера.
- absolute - абсолютный относительно контента сайта. Задаем координаты относительно краев контента (контент может переходить за пределы окна)
- relative - относительно текущей позиции элемента. Фактически мы задаем на сколько подвинуть элемент относительно того, где он должен был показан изначально.
- static - значение по умолчанию.
В общем, нам нужно чтобы подложка нашего диалогового окна начиналась в верхнем левом углу окна и занимала 100% ширины и высоты. Поэтому fixed - координаты относительно окна.
top:0; left: 0;
Координаты элемента. Левый верхний угол окна. Можно задать right, bottom - от правого и нижнего угла. Можно задать только одну из координат, а другая будет по умолчанию (там, где элемент изначально должен был быть показан)
z-index: 500;
z-index задает положение слоев друг над другом. У всего сайта z-index:0. Если хотим, чтобы элемент был поверх - задаем z-index больше, например z-index:1. Мы для модального окна сразу задали 500, чтобы наверняка перекрыть все другие слои, которые будем в будущем делать.
Обратите внимание, что z-index реально будет работать только если один слой находится поверх (или под) другим слоем. То есть у элемента должна быть position:absolute или fixed.
width: 100%; height: 100%;
Ширина и высота блока на всю ширину/высоту окна.
background: rgba(0,0,0,0.8);
Фон подложки полупрозрачный черный - чтобы затемнять контент, поверх которого открывается модальное окно.
display: grid;
grid-template-columns: 1fr;
align-items: center;
Задали отображать дочерние элементы гридом, чтобы не заморачиваться с их вертикальным центрированием.
.modal-content {
Дальше описываем стиль дочернего контейнера, в котором сам диалог будет.
Задали фон черным, если картинка фона не загрузится.
Задали изображение фона. Изображение можно скачать с github по ссылке:
Когда страница откроется, нажмите сверху "Download". Изображение нужно положить в папку img нашего проекта.
Задали, чтобы фон "натягивался" на контейнер и положение центра фона было по центру контейнера.
Задали ширину в 400 px.
margin:0 auto;
Этим мы задаем автоматические отступы слева-справа и центрируем елемент (центрируются элементы или с заданной шириной, или с display:table)
Затемняем фон
Изображение фона яркое. Нам его нужно затемнить, чтобы белый текст читался хорошо. Это мы уже проходили на предыдущих уроках: нужно контент диалога обернуть в еще один контейнер <div> размером на всю высоту-ширину контейнера диалога и в нем задать полупрозрачный темный фон.
В html код такой будет:
В SCSS добавили такой код:
Задали цвет шрифта, размеры на всю ширину-высоту родительского контейнера, полупрозрачный темный фон, убрали внешний отступ, задали внутренний отступ.
Все, с фоном разобрались.
Добавляем кнопку-крестик в углу
Теперь делаем кнопку-крестик в верхнем правом углу, при клике на которую диалог будет закрываться.
Для крестика нам потребуется иконка.
Мы уже знакомы с сервисом иконочного шрифта fontello.com - оттуда и возьмем новую иконку.
Подробно мы о fontello и иконочном шрифте тренировались на занятии 9.
Итак, открываем fontello.com
У вас сайт должен запомнить ваш предыдущий набор иконок. Если открыть вкладку Customize names, то отобразятся иконки, которые мы уже выбирали.
На всякий случай научу, как загрузить восстановить набор иконок из проекта.
Нажимаем на кнопку конфигурации
Там жмем Import
Откроется окно для выбора файла. Открываем папку нашего проекта, папку fonts, папку fontello-xxxxx, и там выбираем файл config.json - в нем хранится вся информация о шрифтах fontello. Файл загрузится и у вас отобразится набор ваших иконок.
Теперь возвращаемся во вкладку Select Icons, в поиске вводим close, находим подходящий нам крестик.
Переходим снова в Customize Names.
Туда добавился наш крестик. Класс иконки будет называться icon-cancel.
Тепер жмем Download Webfont.
Скачается архив со шрифтом. Его нужно распаковать и папку fontello-xxxx перетащить в наш проект в папку fonts.
У вас получится 2 папки fontello-xxxx: новая и старая. Старую нужно удалить.
В general.scss нужно поправить путь к файлу fontello.css на новый (имя папки у нас поменялось)
Обратите внимание, что после fontello- у вас будет другой набор символов - имя папки fontello уникальное.
Иконка есть. Теперь вставляем ее в диалог в index.html
То есть мы добавили контейнер с классом "close-cross-btn" - к нему мы будем применять стили, с помощью которых кнопку поставим в правом верхнем углу диалога.
А саму кнопку мы вставили внутрь этого контейнера и использовали просто класс, который нам выдал fontello. Ну и не забыли вставить неразрывный пробел внутрь ( ), чтобы какие-нибудь "особенные" браузеры не сочли этот элемент пустым и не убрали его с экрана.
Теперь дорабатываем стили.
Я, когда придумывал стили для кнопки, прорабатывал их сначала в правой панели браузера. Потому что, как правило, приходится всегда экспериментировать. А лезть в vscode, писать там, потом идти в хром, обновлять страницу, получать не то, потом опять в vscode не удобно. Лучше сразу в браузере все проработать и готовый код скопировать в vscode.
Итак, код для контейнера кнопки-крестика такой:
position:absolute
Снова position, но со значением absolute. Нам в этот раз положение интересно не относительно окна, а относительно контента документа.
Задали цвет шрифта белый, чтобы кнопка была белого цвета.
Задали положение в верхнем правом углу.
Смотрим результат.
Все как мы и заказывали: в верхнем правом углу. ...только всего документа.
Сейчас мы познаем силу position. Давайте для родительского кнопке элемента modal-content зададим position:relative
Результат нас приятно удивит.
Так вот: position:absolute позиционирует элемент относительно документа либо относительно первого родительского контейнера, у которого задано position:relative.
То есть в первом случае мы задали верхний-правый угол и кнопка расположилась относительно всей страницы.
А во втором случае расположилась в верхнем правом углу относительно родительского элемента с position:relative.
Теперь давайте просто кнопку чуть правее и выше разместим.
Да-да, допустимы и отрицательные значения.
Кстати, с помощью отрицательного значения можно элемент задвинуть за пределы экрана. А потом, например, эффектно его выкатить при каком-либо событии.
Посмотрим результат.
Проблема...
У нас полупрозрачный фон вышел за границы диалога. Причина в том, что мы задали padding и width:100%, а они суммируются между собой. Получилось, что ширина блока: 100% от родительского плюс 2em внутреннего отступа.
Эта проблема решается простым кодом стиля: box-sizing: border-box;
box-sizing как раз говорит браузеру учитывать или не учитывать границы, отступы при подсчете ширины/высоты контейнера.
Посмотрите документацию, чтобы изучить это более подробно:
Давайте теперь заполним диалог текстом:
<p>Свяжемся, обсудим удобный формат, подберем направление, составим программу, начнем твою карьеру в веб-разработке!</p>
<h3>ПОЛУЧИ БЕСПЛАТНО КОНСУЛЬТАЦИЮ И ПЕРВУЮ НЕДЕЛЮ ОБУЧЕНИЯ</h3>
Думаю надо пошире сделать. 500px. И текст внутри диалога центрировать.
Для modal-content ширину увеличим до 500px.
Для modal-dark-bg-wrapper зададим позиционирование текст по центру. text-align: center;
Вот теперь вообще отлично.
HTML формы
Сайт - это все очень хорошо. Но от него смысла нет, если он никак не взаимодействует с пользователем. Задача нашего сайта - дать посетителям доступ к курсам по программированию, а новых пригласить в клуб. Это диалоговое окно должно предложить человеку вступить в клуб, взяв у него номер телефона.
Для этого в диалоге должно быть поле ввода номера телефона и кнопка подтверждения.
Под текстом диалога добавляем следующий код:
<form>
<label for="phone">Телефон для связи</label>
<input type="tel" name="phone" placeholder="+79991112233">
<button type="submit">Поехали!</button>
</form>
<form>
Основной контейнер формы. Все формы должны быть в нем.
<label>
Название поля ввода. В атрибуте for указывается имя поля ввода, к которому относится label.
<input>
Поле ввода. Сюда пользователь вводит данные.
type - тип поля ввода. Может быть text, password, tel и т.д. Мы взяли tel, так как это поле ввода ожидает ввод номера телефона. В случае с password вводимый текст будет скрыт на экране. С случае с tel, на телефонах откроется клавиатура ввода телефона без лишних кнопок типа букв.
name - имя поля ввода. Браузер сохраняет данные заполненных форм и потом автоматически заполняет именно на основе этих данных. А также при отправке формы на сервер, этот name будет отправлен на сервер вместе со значением, которое ввел пользователь.
placeholder - заглушка. Сюда вводятся данные для примера пользователю. Например, пример номера телефона. При клике на поле, placeholder пропадает.
<button> - кнопка. Уже знакомы.
type="submit" - тип кнопки. Submit означает, что роль этой кнопки - отправить форму на сервер.
В _modal.scss внутрь .modal вставляем следующий код:
form {
margin: 1em 0;
label {
display: block;
text-align: left;
margin: 0;
}
input[type="tel"] {
width: 100%;
display: block;
box-sizing: border-box;
margin: 1em 0;
padding: 0.5em;
font-size: 1em;
&:focus {
outline-color: $primary-color;
}
}
button {
display: block;
width: 100%;
margin: 0;
box-sizing: border-box;
}
}
Результат будет вот таким:
Теперь давайте разберем код.
Мы применили стиль для форм внутри диалога. Нужно понимать, что для остальных форм этот стиль применяться не будет (на самом деле мы потом можем переделать стиль).
Для <label> сделали display:block, чтобы подпись отображалась отдельно от других элементов, как самостоятельный блок. Убрали отступы и сделали отбивку текста по центру.
input[type="tel"]
Новый вид записи селектора css для нас. С input все понятно - мы применили к тегу. А в квадратных скобках можно указать значение атрибута тега, при котором правило будет применяться.
То есть у нас у тега задан атрибут type со значением tel. Если это так, то наш стиль будет применяться.
Подстроили отступы, ширину, размер текста. Все уже знакому. Ну и box-sizing: border-box указали, чтобы внутренний отступ не распирал общую ширину элемента.
&:focus
Указали правило на случай, когда поле ввода находится в фокусе (в него нажали и сейчас там можно вводить текст).
outline - это почти тоже самое, что border. Это рамка. Только border учитывается при общей ширине, а outline на ширину никак не влияет.
Ну и, на самом деле, мы указали цвет для outline потому что в браузерах по умолчанию свой цвет используется. Нам он не подходит по стилю - мы используем свой primary-color.
Со стилем button вам уже должно быть все понятно.
Все, диалог нарисовали полностью. Теперь самое интересное: нам нужно его отображать при клике на кнопку.
Результаты этого урока можете скачать здесь:
https://github.com/madmaker/srmt22-lsn12/archive/refs/tags/v1.zip
Что делать дальше и как нам помочь?
1. Поставить лайк
2. Написать в комментарии, за сколько времени удалось сделать урок, с чем возникли сложности, что бы хотелось разобрать более детально
3. Подписаться на этот канал
4. Добавиться к нам в группу в наш открытый клуб веб-разработки в телеграм: https://t.me/srmt22_webclub
5. Сделать репост этого урока себе в соцсети.
Что будет на следующем занятии?
Начнем изучать Javascript. Вот здесь уже начнется серьезное программирование.
Трудоустройство
Те, кто хочет индивидуальное обучение с преподавателем и быстрое гарантированное трудоустройство, пишите нам в телеграм: