Воссоздаем YouTube с помощью HTML и CSS
До сих пор мы рассматривали основы HTML и CSS, обсуждали различные методы, позволяющие размещать элементы на веб-странице, и изучали концепцию адаптивного дизайна, которая позволяет создавать веб-страницы, автоматически адаптирующиеся к различным размерам экрана. В этой главе мы объединим все, что мы узнали до сих пор, чтобы воссоздать YouTube, используя только HTML и CSS.
▶️ YouTube Demo
📧 Подпишитесь на мою рассылку: https://ericsdevblog.ck.page/profile
Создание макета страницы
Давайте начнем с обсуждения базового макета страницы. Мы будем следовать правилу "сначала для мобильных устройств" и начнем с маленького экрана. На маленьком экране должна быть верхняя панель навигации и раздел содержимого. Панель навигации имеет логотип слева и несколько кнопок справа. Раздел содержимого должен включать несколько компонентов-карточек, показывающих отдельные видеоролики.
На экране среднего размера (>= 640 пикселей) на панели навигации должно отображаться больше значков. Мы пока пропустим этот шаг и вернемся к этой теме, когда начнем создавать навигационное меню.
На большом экране (>= 768 пикселей) страница должна иметь небольшую боковую панель. На панели навигации должно отображаться окно поиска в центре, а не просто значок. Раздел содержимого также должен быть многоколоночным.
И, наконец, на экране x-large (>= 1024 пикселей) веб-страница должна иметь полноразмерную боковую панель, полностью развернутую панель навигации со всеми значками и полями поиска, а в разделе содержимого должно быть больше столбцов.
HTML-документ
Теперь давайте посмотрим, сможете ли вы создать этот макет. Мы начнем с HTML-документа. Мы начнем с панели навигации:
<header>
<nav>
<div class="start">
<div>Button</div>
<div>Logo</div>
</div>
<div class="center">
<div>Search</div>
<div>Microphone</div>
</div>
<div class="end">
<div>Button</div>
<div>Button</div>
<div>Button</div>
</div>
</nav>
</header>
А затем боковые панели:
<main>
<aside class="sidebar-sm">Small sidebar</aside>
<aside class="sidebar-full">Full sidebar</aside>
. . .
</main>
Внутри элемента <main>
также должен быть раздел content
:
<section class="content">
<section class="video">
<div class="video-thumbnail">
<img src="video_thumbnail1.jpg" alt="Video Thumbnail" />
</div>
<div class="video-info">
<img src="channel1.jpg" alt="Channel Logo" />
<div>
<h2>Video Title 1</h2>
<p>Channel Name</p>
<p>1M views • 1 day ago</p>
</div>
</div>
</section>
. . .
</section>
Помните, что ваш HTML-код должен содержать все компоненты, необходимые для всех размеров экрана. Если элемент не требуется для определенного экрана, вы можете удалить его, установив значение display
равным none
.
Этот пример содержит панель навигации, определяемую элементом <nav>
. Панель навигации состоит из трех разделов: start
, center
и end
. Названия классов соответствуют их соответствующим позициям на панели навигации. Этот макет можно создать с помощью flexbox, а для свойства justify-content
должно быть установлено значение space-between
. Центральную секцию следует снимать до тех пор, пока экран не станет достаточно большим.
Раздел <main>
имеет две боковые панели: небольшую боковую панель (sidebar-sm
) и полноразмерную боковую панель (sidebar-full)
. Маленькая боковая панель должна отображаться на больших экранах, а полноразмерная боковая панель должна отображаться только на экранах x-large.
Наконец, для раздела содержимого вы можете использовать CSS-сетку с адаптивным макетом без точки останова, который мы обсуждали в предыдущей главе. На данный момент мы не будем беспокоиться о том, как создаются компоненты карты.
Теперь мы можем перейти к файлу CSS. Давайте уберем поля и отступы по умолчанию и установим для свойства box-sizing
значение border-box
. Вы также можете добавить рамку к каждому разделу, чтобы сделать их соответствующие позиции более четкими.
* {
box-sizing: border-box;
padding: 0px;
margin: 0px;
}
nav,
.sidebar-sm,
.sidebar-full,
.content {
border: black solid 2px;
}
Макет навигационной панели
Далее, панель навигации должна представлять собой flexbox с направлением, установленным на строку, и параметром justify-content
, установленным на пространство между ними, чтобы каждый подраздел имел равные промежутки между собой. Подразделы также должны представлять собой flexbox строк, чтобы логотип и значки также располагались горизонтально. Однако, поскольку мы начинаем с маленького экрана, центральную часть на данный момент следует удалить (display: none;
).
nav {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.start {
display: flex;
flex-direction: row;
}
.center {
display: none; /* Not displayed on small screens */
}
.end {
display: flex;
flex-direction: row;
}
For large screens, the center section should be designed just like its siblings.
/* Large screen */
@media screen and (min-width: 768px) {
.center {
display: flex;
flex-direction: row;
}
}
Боковые панели
Далее, раздел <main>
должен представлять собой флексбокс строк или сетку с двумя столбцами, чтобы боковая панель и контент находились в одной строке.
main {
display: flex;
flex-direction: row;
}
The sidebars are removed on small screens.
.sidebar-sm {
display: none;
}
.sidebar-full {
display: none;
}
Маленькая боковая панель отображается на больших экранах. Установив для flex
значение 0
, вы гарантируете, что боковая панель имеет фиксированный размер и при изменении области просмотра изменяется только раздел контента.
/* Large screen */
@media screen and (min-width: 768px) {
.center {
display: flex;
flex-direction: row;
}
.sidebar-sm {
display: flex;
flex-direction: column;
flex: 0;
}
}
Полноразмерная боковая панель отображается на больших экранах, а маленькая боковая панель будет удалена.
/* X-Large screen */
@media screen and (min-width: 1024px) {
.sidebar-sm {
display: none;
}
.sidebar-full {
display: flex;
flex-direction: column;
flex: 0;
}
}
Раздел контента
Наконец, для раздела контента:
.content {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(20em, 1fr));
grid-gap: 1em;
flex: 1;
}
.video {
border: red solid 2px;
width: 100%;
}
На данный момент мы установим максимальную ширину видеокарты равной 20 мкм. Вот как выглядит этот макет при изменении области просмотра:
Построение панели навигации
Далее давайте сосредоточимся на панели навигации. В разделе "Пуск" есть значок меню и логотип. Центральная секция содержит форму поиска и значок поиска. Наконец, конечная секция содержит несколько значков и фотографию профиля. Чтобы сделать этот пример короче, я опустил фактические элементы значков, определенные с помощью <svg>
, но вы можете скопировать эти ресурсы непосредственно с YouTube.
<nav>
<div class="start">
<div class="menu-icon">. . .</div>
<img src="images/logo.png" alt="YouTube Logo" />
</div>
<div class="center">
<form action="/">
<input type="text" placeholder="Search" />
<button>
<div class="search-form-icon">. . .</div>
</button>
</form>
<div class="mic-icon-center">. . .</div>
</div>
<div class="end">
<div class="search-icon">. . .</div>
<div class="mic-icon">. . .</div>
<div class="camera-icon">. . .</div>
<div class="notification-icon">. . .</div>
<img src="images/profile.jpg" alt="Profile Image" />
</div>
</nav>
Прежде всего, все значки должны иметь единый стиль. Они должны быть округлыми и иметь одинаковые отступы. У значков также должен быть фон при наведении курсора сверху.
.menu-icon,
.search-icon,
.mic-icon,
.mic-icon-center,
.camera-icon,
.notification-icon {
border-radius: 100%;
padding: 10px;
}
svg {
display: block;
width: 100%;
height: 100%;
}
.menu-icon:hover,
.search-icon:hover,
.mic-icon:hover,
.mic-icon-center:hover,
.camera-icon:hover,
.notification-icon:hover {
background-color: #e5e5e5;
}
На маленьком экране большинство этих значков следует удалить, поскольку горизонтальное пространство на мобильном устройстве очень ценно. В этом случае мы сохраним только логотип, значок поиска и изображение профиля. Все остальные элементы будут удалены.
.menu-icon,
.mic-icon,
.mic-icon-center,
.camera-icon,
.notification-icon {
display: none;
}
А затем оформите начальную, центральную и конечную части навигационной панели.
/* Navbar start section */
.start {
display: flex;
flex-direction: row;
flex: 1;
gap: 10px;
padding: 8px;
align-items: center;
}
.start > img {
width: 90px;
}
/* Navbar center section */
.center {
display: none;
flex: 2;
}
/* Navbar end section */
.end {
display: flex;
flex-direction: row;
padding: 8px;
align-items: center;
justify-content: end;
flex: 1;
}
.end > img {
width: 40px;
border-radius: 100%;
object-fit: cover;
margin-left: 10px;
}
start
и end
будут иметь одинаковый размер, а center
будет увеличиваться быстрее, чем его братья и сестры, по мере увеличения области просмотра. center
будет удален на маленьком экране, поэтому пока есть только начало и конец.
На экране среднего размера появится больше значков, но центральная часть по-прежнему удалена.
@media screen and (min-width: 640px) {
/* Display the menu, mic, camera, and notification icons for medium screen */
.menu-icon,
.mic-icon,
.camera-icon,
.notification-icon {
display: block;
}
}
На большом экране отобразится центральная часть, значок микрофона будет перемещен в центр, а значок поиска справа будет удален. Я не указал стили для формы поиска.
@media screen and (min-width: 768px) {
.sidebar-sm {
display: flex;
flex-direction: column;
flex: 0;
}
/* Display the center section for large screens */
.center {
display: flex;
flex-direction: row;
gap: 10px;
padding: 8px;
align-items: center;
justify-content: center;
}
. . .
/* Hide the search and right mic icons */
.search-icon,
.mic-icon {
display: none;
}
/* Display the center mic icon */
.mic-icon-center {
display: block;
}
}
Создание боковой панели
Теперь перейдем к боковой панели. Небольшая боковая панель будет отображаться на больших экранах, а полноразмерная боковая панель — на больших экранах.
<aside class="sidebar-sm">
<div class="side-icon">
<div class="icon">. . .</div>
<div class="text">Home</div>
</div>
. . .
</aside>
<aside class="sidebar-full">
<section class="guide">
<div class="item">
<div class="icon">. . .</div>
<div class="text">Home</div>
</div>
. . .
<div class="divider"></div>
<div class="item">
<div class="icon">. . .</div>
<div class="text">Library</div>
</div>
. . .
</section>
<div class="divider"></div>
<section class="subscriptions">
<p>Subscriptions</p>
<div class="item">
<img src="images/1.jpg" alt="Channel1" />
<div class="text">First channel</div>
</div>
. . .
</section>
<div class="divider"></div>
<section class="explore">
<p>Explore</p>
<div class="item">
<div class="icon">. . .</div>
<div class="text">Trending</div>
</div>
. . .
</section>
<div class="divider"></div>
<section class="mf-ytb">
<p>More from YouTube</p>
<div class="item">
<div class="icon">. . .</div>
<div class="text">YouTube Premium</div>
</div>
. . .
</section>
</aside>
Небольшая боковая панель содержит четыре кнопки, расположенные вертикально. Каждая отдельная кнопка также должна представлять собой гибкий блок, выровненный по вертикали.
@media screen and (min-width: 768px) {
.sidebar-sm {
display: flex;
flex-direction: column;
flex: 0;
}
.side-icon {
width: 80px;
height: 100px;
border-radius: 10px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.side-icon:hover {
background-color: #f2f2f2;
}
.side-icon svg {
width: 25px;
}
.side-icon > .text {
font-size: 10px;
margin-top: 5px;
}
. . .
}
Что касается полноразмерной боковой панели, то она должна отображаться только на экранах x-large. Боковая панель должна иметь фиксированную ширину (flex: 0 250 пикселей;), чтобы она не менялась при изменении размера окна просмотра. Высота определяется как 100 процентов от высоты окна просмотра (100vh), а для переполнения установлено значение auto
. Эта конфигурация гарантирует, что боковая панель рассматривается как отдельный раздел веб-страницы. Когда вы прокручиваете боковую панель вверх и вниз, это не повлияет на другие части страницы.
@media screen and (min-width: 1024px) {
.sidebar-sm {
display: none;
}
.sidebar-full {
display: flex;
flex-direction: column;
flex: 0 250px;
height: 100vh;
overflow-y: auto;
padding: 8px;
}
. . .
}
Для отдельных элементов на боковой панели настройка должна быть простой для понимания.
@media screen and (min-width: 1024px) {
.sidebar-sm {
display: none;
}
.sidebar-full {
display: flex;
flex-direction: column;
flex: 0 250px;
height: 100vh;
overflow-y: auto;
padding: 8px;
}
/* Section titles */
.subscriptions > p,
.explore > p,
.mf-ytb > p {
font-size: 16px;
padding: 10px;
}
/* Individual items */
.item {
display: grid;
grid-template-columns: 25px auto;
gap: 20px;
align-items: center;
justify-items: stretch;
padding: 10px;
border-radius: 10px;
}
.item:hover {
background-color: #f2f2f2;
}
.item > .text {
font-size: 14px;
}
/* Channel images */
.item > img {
width: 30px;
aspect-ratio: 1/1;
border-radius: 100%;
object-fit: cover;
}
/* Divider */
.divider {
border: #e5e5e5 solid 1px;
margin: 10px 0px;
}
}
Сборка компонента видеокарты
Что касается раздела контента, то у нас уже готов общий макет. Все, что вам нужно сделать, это создать компонент видеокарты.
<section class="content">
<section class="video">
<div class="video-thumbnail">
<img src="images/1.jpg" alt="Video Thumbnail" />
</div>
<div class="video-info">
<img src="images/2.jpg" alt="Channel Logo" />
<div>
<h2>Lorem ipsum dolor sit amet consectetur adipisicing elit</h2>
<p>Channel Name</p>
<p>1M views • 1 day ago</p>
</div>
</div>
</section>
. . .
</section>
/* Video card */
.video {
width: 100%;
height: min-content;
}
.video-thumbnail > img {
width: 100%;
height: 15em;
object-fit: cover;
border-radius: 10px;
}
.video-info {
display: grid;
grid-template-columns: 50px auto;
gap: 10px;
padding: 10px 0px;
}
.video-info > img {
width: 50px;
height: 50px;
border-radius: 100%;
object-fit: cover;
}
.video-info > div {
display: flex;
flex-direction: column;
gap: 5px;
}
.video-info h2 {
font-weight: 700;
font-size: 20px;
}
.video-info p {
color: #606060;
font-size: 14px;
}
Сам элемент content
также должен быть независимым, как боковая панель.
Вывод
В этой главе мы взяли все, что мы узнали до сих пор о HTML и CSS, и воссоздали домашнюю страницу YouTube. На этом примере мы в значительной степени рассмотрели все, что вам следует знать о HTML и CSS.