ЖСО-201/2. Цифровые коммуникации. Практическое задание №9. Сложный имиджевый лендинг
Вам нужно создать сложный имиджевый лендинг, содержащий:
- шесть иллюстраций, собранных в 3D-куб;
- подложку, используемую как основной фон;
- шесть карточек с текстом, реализованных на прозрачном фоне и привязанных к сторонам куба;
- имена иллюстраций, наложенных на фото;
- прогресс-бар с отображением имени выбранного фото.
CSS
1) Создаем класс упаковки, в котором будет находиться весь проект:
.box {
width: 110%;
padding: 40px;
position: absolute;
overflow: hidden;
}
2) Встраиваем шрифт (можете использовать свой):
@import url("https://fonts.googleapis.com/css2?family=Bebas+Neue&family=DM+Mono:wght@300;400&display=swap");
3) Встраиваем миксины слоев, которые пойдут ниже:
@layer reset, tokens, base, layout, cube, ui, cards, reveal, theme, responsive;
4) Миксин общей упаковки:
@layer reset {
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
}
5) Миксин слоя с базовыми цветами и шрифтами (переходы теней и границы):
@layer tokens {
:root {
color-scheme: light;
--dark-bg: #1c1814;
--dark-fg: #ede8df;
--dark-muted: #8a7b6e;
--light-bg: #f0ece3;
--light-fg: #0d0d14;
--light-muted: #9a9aaa;
--accent-dark: #d4a84b;
--accent-light: #3a6e00;
--bg: var(--dark-bg);
--fg: var(--dark-fg);
--muted: var(--dark-muted);
--accent: var(--accent-dark);
--font-display: "Bebas Neue", sans-serif;
--font-mono: "DM Mono", monospace;
--hairline: 0.0625rem;
--ui-inset: 2rem;
--card-bg: rgba(28, 24, 20, 0.82);
--card-border: rgba(212, 168, 75, 0.2);
--nav-x: calc(var(--ui-inset) + 0.125rem);
--reveal-offset: 0.625rem;
--reveal-duration: 0.5s;
--z-ui: 10;
}
}
6) Миксин базы проекта. Здесь в селекторе body укажите фоновую иллюстрацию:
@layer base {
html {
color-scheme: light;
}
body {
font-family: var(--font-mono);
overflow-x: hidden;
transition: background 0.3s ease, color 0.3s ease;
background: url('ваш фон');
}
}
7) Миксин слоя сцены, контейнера и секции:
@layer layout {
#scene {
position: fixed;
inset: 0;
z-index: 0;
display: flex;
align-items: center;
justify-content: center;
perspective: 1100px;
pointer-events: none;
}
#scroll_container {
position: relative;
margin-left: -250px;
z-index: 999;
}
section {
min-height: 100vh;
display: flex;
align-items: center;
padding: 6rem calc(5rem + var(--ui-inset)) 6rem 5rem;
}
}
8) Миксин 3D-куба, составляющих его граней, иллюстраций в этих гранях и поворотов этих граней:
@layer cube {
#cube {
--s: min(74vw, 74vh, 560px);
width: var(--s);
height: var(--s);
position: relative;
transform-style: preserve-3d;
transform: rotateX(90deg) rotateY(0deg);
will-change: transform;
}
.face {
position: absolute;
inset: 0;
overflow: hidden;
backface-visibility: hidden;
img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
&:has(img) .face-ph {
display: none;
}
}
.face-ph {
position: absolute;
bottom: 1.5rem;
left: 1.75rem;
font-family: var(--font-display);
font-size: clamp(2rem, 8vw, 5rem);
letter-spacing: 0.04em;
color: white;
pointer-events: none;
user-select: none;
}
.face[data-face="front"] {
transform: translateZ(calc(var(--s) / 2));
}
.face[data-face="back"] {
transform: rotateY(180deg) translateZ(calc(var(--s) / 2));
}
.face[data-face="right"] {
transform: rotateY(90deg) translateZ(calc(var(--s) / 2));
}
.face[data-face="left"] {
transform: rotateY(-90deg) translateZ(calc(var(--s) / 2));
}
.face[data-face="top"] {
transform: rotateX(-90deg) translateZ(calc(var(--s) / 2));
}
.face[data-face="bottom"] {
transform: rotateX(90deg) translateZ(calc(var(--s) / 2));
}
}
9) Миксин с заполняемым прогресс-баром вверху. В классе progress-fill используйте свой цвет:
@layer ui {
#upbar {
position: fixed;
top: var(--ui-inset);
right: var(--ui-inset);
z-index: var(--z-ui);
text-align: right;
font-size: 0.65rem;
letter-spacing: 0.15em;
color: var(--muted);
text-transform: uppercase;
.progress-bar {
width: 7.5rem;
height: var(--hairline);
background: var(--muted);
margin-block-start: 0.5rem;
margin-inline-start: auto;
position: relative;
overflow: hidden;
}
.progress-fill {
position: absolute;
inset-block: 0;
inset-inline-start: 0;
width: 0%;
background: ваш цвет;
transition: width 0.1s linear;
}
.scene-label {
font-size: 0.6rem;
color: var(--accent);
margin-block-start: 0.4rem;
}
}
10) Каптивы текста и нумерации поверх иллюстраций куба:
#face_caption {
position: fixed;
bottom: var(--ui-inset);
left: 50%;
translate: -50% 0;
z-index: var(--z-ui);
text-align: center;
pointer-events: none;
user-select: none;
}
#face_caption_num {
font-size: 0.58rem;
letter-spacing: 0.28em;
color: var(--accent);
text-transform: uppercase;
margin-block-end: 0.15rem;
}
#face_caption_name {
font-family: var(--font-display);
font-size: clamp(1.8rem, 5vw, 3.5rem);
letter-spacing: 0.08em;
color: white;
line-height: 1;
}
11) Теперь идентификатор текста слева и ссылки в нем:
#left-text {
position: fixed;
left: -12%;
top: 40%;
transform: translateY(-50%) rotate(-90deg);
transform-origin: right center;
z-index: var(--z-ui);
font-family: var(--font-mono);
font-size: 0.65rem;
letter-spacing: 0.15em;
text-transform: uppercase;
a {
color: var(--muted);
text-decoration: none;
}
}
}
12) Аналогичный идентификатор с текстом справа:
#right-text {
position: fixed;
right: 5%;
top: 65%;
transform: translateY(50%) rotate(90deg);
transform-origin: right center;
z-index: var(--z-ui);
font-family: var(--font-mono);
font-size: 0.65rem;
letter-spacing: 0.15em;
text-transform: uppercase;
}
13) Слой карточек на прозрачном фоне:
@layer cards {
.text-card {
max-width: 23.75rem;
padding: 2.25rem 2rem;
background: var(--card-bg);
border-left: var(--hairline) solid var(--card-border);
backdrop-filter: blur(6px) saturate(120%);
-webkit-backdrop-filter: blur(6px) saturate(120%);
overflow: hidden;
transition: background 0.3s ease, border-color 0.3s ease;
&.right {
margin-inline-start: auto;
border-left: none;
border-right: var(--hairline) solid var(--card-border);
text-align: right;
}
&.center {
margin-inline: auto;
border-left: none;
border-top: var(--hairline) solid var(--card-border);
text-align: center;
max-width: 28.75rem;
}
}
14) Тег в верхней части карточки и параметры заголовков:
.tag {
font-size: 0.6rem;
letter-spacing: 0.25em;
text-transform: uppercase;
color: var(--accent);
margin-block-end: 1.1rem;
}
:where(h1, h2) {
font-family: var(--font-display);
font-weight: 400;
letter-spacing: 0.03em;
line-height: 0.92;
}
h1 {
font-size: clamp(3rem, 8vw, 6.5rem);
}
h2 {
font-size: clamp(2.2rem, 5vw, 4rem);
}
15) Поле основного текста в карточке:
.body-text {
font-size: 0.78rem;
line-height: 1.8;
color: black;
margin-block-start: 1.25rem;
}
16) Поле с кнопками навигации под карточкой и макет рамки кнопок:
.button-row {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 0.75rem;
margin-block-start: 1.75rem;
}
.text-card.right .button-row {
justify-content: flex-end;
}
.button {
display: inline-flex;
align-items: center;
gap: 0.6rem;
padding: 0.6rem 1.25rem;
border: var(--hairline) solid var(--accent);
color: var(--accent);
font-family: var(--font-mono);
font-size: 0.62rem;
letter-spacing: 0.18em;
text-transform: uppercase;
text-decoration: none;
cursor: pointer;
transition: background 0.2s, color 0.2s;
&:hover {
background: var(--accent);
color: var(--bg);
}
svg {
width: 0.6875rem;
height: 0.6875rem;
}
}
.button-back {
display: inline-flex;
align-items: center;
gap: 0.6rem;
padding: 0.6rem 1.25rem;
border: var(--hairline) solid
color-mix(in srgb, var(--muted) 45%, transparent);
color: var(--muted);
font-family: var(--font-mono);
font-size: 0.62rem;
letter-spacing: 0.18em;
text-transform: uppercase;
text-decoration: none;
transition: background 0.2s, color 0.2s, border-color 0.2s;
&:hover {
background: color-mix(in srgb, var(--muted) 12%, transparent);
border-color: var(--muted);
color: var(--fg);
}
svg {
width: 0.6875rem;
height: 0.6875rem;
}
}
}
17) Слой отображения карточек поверх базового слоя:
@layer reveal {
:is(.tag, h1, h2, .body-text, .button, .button-back) {
opacity: 0;
translate: 0 var(--reveal-offset);
}
:is(h1, h2) {
translate: 0 1.125rem;
transition: opacity var(--reveal-duration) ease 0.08s,
translate var(--reveal-duration) ease 0.08s;
}
.tag {
transition: opacity var(--reveal-duration) ease,
translate var(--reveal-duration) ease;
}
.body-text {
transition: opacity var(--reveal-duration) ease 0.2s,
translate var(--reveal-duration) ease 0.2s;
}
:is(.button, .button-back) {
transition: opacity var(--reveal-duration) ease 0.35s,
translate var(--reveal-duration) ease 0.35s, background 0.2s, color 0.2s,
border-color 0.2s;
}
:is(.tag, h1, h2, .body-text, .button, .button-back).visible {
opacity: 1;
translate: 0 0;
}
}
18) Слой основных настроект проекта:
@layer theme {
:root {
color-scheme: light;
--bg: var(--light-bg);
--fg: var(--light-fg);
--muted: var(--light-muted);
--accent: var(--accent-light);
--card-bg: rgba(240, 236, 227, 0.08);
--card-border: rgba(58, 110, 0, 0.14);
.face {
background: repeating-linear-gradient(
0deg,
rgba(0, 0, 0, 0.05) 0,
rgba(0, 0, 0, 0.05) 1px,
transparent 1px,
transparent 48px
),
repeating-linear-gradient(
90deg,
rgba(0, 0, 0, 0.05) 0,
rgba(0, 0, 0, 0.05) 1px,
transparent 1px,
transparent 48px
),
#ddd8cf;
}
.face-ph {
color: rgba(0, 0, 0, 0.07);
}
}
#face_caption_name {
opacity: 0.35;
}
}
}
19) Слой параметров для мобайла:
@layer responsive {
@media (width <= 56.25em) {
#upbar {
top: 1rem;
right: 1rem;
}
#scene_strip {
display: none;
}
#left-text {
display: none;
}
#right-text {
display: none;
}
#theme_toggle {
bottom: 1rem;
left: 1.25rem;
translate: 0 0;
}
#face_caption {
bottom: 1rem;
}
section {
min-height: 150vh;
align-items: flex-end;
padding: 0 1.5rem 3.5rem;
}
#s0 {
min-height: 100vh;
align-items: center;
padding: 4rem 1.5rem;
}
:is(.text-card, .text-card.right, .text-card.center) {
max-width: 100%;
padding: 1.5rem 1.25rem;
}
.body-text {
line-height: 1.55;
}
.button-row {
margin-block-start: 1.25rem;
}
}
}
20) Теперь задаем идентификаторы для секций, которые будут выводиться слева - их три:
#s0 {
position: relative;
margin-left: 100px;
z-index: 9999;
}
#s2 {
position: relative;
margin-left: 100px;
z-index: 9999;
}
#s4 {
position: relative;
margin-left: 100px;
z-index: 9999;
}
JavaScript
21) В динамичном сценарии нужно указать ссылки на иллюстрации сторон куба. Они должны быть одинаковыми. Загрузите фото (6) в репозиторий:
const IMAGE_SRCS = [
"фото1",
"фото2",
"фото3",
"фото4",
"фото5",
"фото6"
];
22) теперь указать масштаб:
const IMAGE_ASPECTS = [1, 1, 1, 1, 1, 1];
23) И их имена в используемом вами порядке:
const FACE_NAMES = [
"LUNCH",
"A MASKED BALL",
"THE SUBWAY",
"GOVERNMENT BUREAU",
"THE WAITING ROOM",
"LANDSCAPE WITH FIGURES"
];
23.1) Отдельным файлом добавляем конфигурацию JavaScript проекта. Взять ее можно здесь: https://raw.githubusercontent.com/Dmitrykonn/network/refs/heads/main/cubescroll.js
HTML
24) Указываем стандартные теги и имя проекта:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ваш заголовок</title>
25) Встраиваем шрифты Google. Если используете свой шрифт - укажите корректную ссылку:
<link href="https://fonts.googleapis.com" rel="preconnect">
<link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=DM+Mono:wght@300;400&display=swap" rel="stylesheet">
26) Встраиваем CSS, закрываем </head>, открываем <body>
27) Открываем класс упаковки проекта и сцены:
<div class="box">
<div id="scene">
28) Теперь класс 3D-куба с 6 сторонами:
<div id="cube">
<div class="face" data-face="top" data-i="0"><span class="face-ph">TOP</span></div>
<div class="face" data-face="front" data-i="1"><span class="face-ph">FRONT</span></div>
<div class="face" data-face="right" data-i="2"><span class="face-ph">RIGHT</span></div>
<div class="face" data-face="back" data-i="3"><span class="face-ph">BACK</span></div>
<div class="face" data-face="left" data-i="4"><span class="face-ph">LEFT</span></div>
<div class="face" data-face="bottom" data-i="5"><span class="face-ph">BOTTOM</span></div>
29) Закрываем класс куба и сцены:
</div>
</div>
30) Добавляем класс прогресс-бара:
<div id="upbar">
<div id="upbar_pct">000%</div>
<div class="progress-bar">
<div class="progress-fill" id="prog_fill"></div>
</div>
<div class="scene-label" id="scene_name">DESCENT</div>
</div>
31) Общий макет секций - их 6 как и сторон куба:
<button id="theme_toggle"></button>
<div id="scene_strip">
<a class="scene-dot active" href="#s0"></a>
<a class="scene-dot" href="#s1"></a>
<a class="scene-dot" href="#s2"></a>
<a class="scene-dot" href="#s3"></a>
<a class="scene-dot" href="#s4"></a>
<a class="scene-dot" href="#s5"></a>
</div>
32) Каптива на сторонах куба:
<div id="face_caption">
<div id="face_caption_num">01</div>
<div id="face_caption_name">LUNCH</div>
</div>
33) Теперь переходим к карточкам и указываем идентификатор контейнера:
<div id="scroll_container">
34) Первая секция. Обратите внимание, что в каждой секции меняется цвет тега и цвет заголовка. Кроме того, в первой карточке только одна кнопка с навигацией вперед:
<section id="s0">
<div class="text-card">
<div class="tag" style="color: Olive">Верхний тег карточки</div>
<h2 style="color: Olive">ЗАГОЛОВОК КАРТОЧКИ</h2>
<p class="body-text">
Текст карточки.
</p>
<div class="button-row">
<a class="button" href="#s1">
Кнопка вперед
<svg fill="none" stroke-width="1.5" stroke="currentColor" viewbox="0 0 12 12">
<path d="M1 6h10M6 1l5 5-5 5">
</path></svg>
</a>
</div>
</div>
</section>
35) Вторая секция:
<section id="s1">
<div class="text-card right">
<div class="tag" style="color: DarkOrange">Верхний тег карточки</div>
<h2 style="color: DarkOrange">ЗАГОЛОВОК<br />КАРТОЧКИ</h2>
<p class="body-text">
Текст карточки.
</p>
<div class="button-row">
<a class="button-back" href="#s0">
<svg fill="none" stroke-width="1.5" stroke="currentColor" viewbox="0 0 12 12">
<path d="M11 6H1M6 11L1 6l5-5">
</path></svg>
Кнопка назад
</a>
<a class="button" href="#s2">
Кнопка вперед
<svg fill="none" stroke-width="1.5" stroke="currentColor" viewbox="0 0 12 12">
<path d="M1 6h10M6 1l5 5-5 5">
</path></svg>
</a>
</div>
</div>
</section>
36) Третья:
<section id="s2">
<div class="text-card">
<div class="tag" style="color: OrangeRed">Верхний тег карточки</div>
<h2 style="color: OrangeRed">ЗАГОЛОВОК<br />КАРТОЧКИ</h2>
<p class="body-text">
Текст карточки.
</p>
<div class="button-row">
<a class="button-back" href="#s1">
<svg fill="none" stroke-width="1.5" stroke="currentColor" viewbox="0 0 12 12">
<path d="M11 6H1M6 11L1 6l5-5">
</path></svg>
Кнопка назад
</a>
<a class="button" href="#s3">
Кнопка вперед
<svg fill="none" stroke-width="1.5" stroke="currentColor" viewbox="0 0 12 12">
<path d="M1 6h10M6 1l5 5-5 5">
</path></svg>
</a>
</div>
</div>
</section>
37) Четвертая:
<section id="s3">
<div class="text-card right">
<div class="tag" style="color: DarkKhaki">Верхний тег карточки</div>
<h2 style="color: DarkKhaki">ЗАГОЛОВОК<br />КАРТОЧКИ</h2>
<p class="body-text">
Текст карточки.
</p>
<div class="button-row">
<a class="button-back" href="#s2">
<svg fill="none" stroke-width="1.5" stroke="currentColor" viewbox="0 0 12 12">
<path d="M11 6H1M6 11L1 6l5-5">
</path></svg>
Кнопка назад
</a>
<a class="button" href="#s4">
Кнопка вперед
<svg fill="none" stroke-width="1.5" stroke="currentColor" viewbox="0 0 12 12">
<path d="M1 6h10M6 1l5 5-5 5">
</path></svg>
</a>
</div>
</div>
</section>
38) Пятая:
<section id="s4">
<div class="text-card">
<div class="tag" style="color: teal">Верхний тег карточки</div>
<h2 style="color: teal">ЗАГОЛОВОК<br />КАРТОЧКИ</h2>
<p class="body-text">
Текст карточки.
</p>
<div class="button-row">
<a class="button-back" href="#s3">
<svg fill="none" stroke-width="1.5" stroke="currentColor" viewbox="0 0 12 12">
<path d="M11 6H1M6 11L1 6l5-5">
</path></svg>
Кнопка назад
</a>
<a class="button" href="#s5">
Кнопка вперед
<svg fill="none" stroke-width="1.5" stroke="currentColor" viewbox="0 0 12 12">
<path d="M1 6h10M6 1l5 5-5 5">
</path></svg>
</a>
</div>
</div>
</section>
39) Финальная, шестая секция. Здесь нет кнопки вперед, но есть кнопка, возвращающая к началу:
<section id="s5">
<div class="text-card right">
<div class="tag" style="color: orange">Верхний тег карточки</div>
<h2 style="color: orange">ЗАГОЛОВОК<br />КАРТОЧКИ</h2>
<p class="body-text">
Текст карточки.
</p>
<div class="button-row">
<a class="button-back" href="#s4">
<svg fill="none" stroke-width="1.5" stroke="currentColor" viewbox="0 0 12 12">
<path d="M11 6H1M6 11L1 6l5-5">
</path></svg>
Кнопка назад
</a>
<a class="button" href="#s0">
Кнопка к началу
<svg fill="none" stroke-width="1.5" stroke="currentColor" viewbox="0 0 12 12">
<path d="M1 6h10M6 1l5 5-5 5">
</path></svg>
</a>
</div>
</div>
</section>
40) Закрываем контейнер:
</div>
41) Теперь добавляем идентификаторы текста слева и справа. Укажите в них адрес ссылок, кегль, шрифт и цвет:
<div id="left-text">
<a href="#" rel="noopener" target="_blank"><font size="14" face="Bebas Neue" color="grey">ВАШ ТЕКСТ</font></a>
</div>
<div id="right-text">
<a href="#" rel="noopener" target="_blank"><font size="14" face="Bebas Neue" color="grey">ВАШ ТЕКСТ</font></a>
</div>
42) Закрываем класс проекта:
</div>
43) Встройте первый и второй JavaScript
44) Закройте оставшиеся теги
</body>
</html>
Если все верно, то ваш проект будет выглядеть примерно так: https://konoplevdesign3.blogspot.com/p/3d-flat-glassmorphism-composite.html
Ссылки на выполненное задание принимаются в комментариях к данному посту для группы ЖСО-202 до 10:00 21 апреля. Для группы ЖСО-201 до 10:00 28 апреля.
https://shimanskayadasha.blogspot.com/p/pharaoh-top-front-right-back-left.html Шиманская Дарья ЖСО-202
ОтветитьУдалить