Основы веб-разработки: CSS и JavaScript

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

1. Основы CSS: селекторы, блочная модель и позиционирование элементов

Основы CSS: селекторы, блочная модель и позиционирование элементов

Добро пожаловать в курс «Основы веб-разработки: CSS и JavaScript». Если HTML — это скелет веб-страницы, определяющий её структуру и содержание, то CSS (Cascading Style Sheets) — это её кожа, одежда и макияж. Именно CSS превращает скучный список заголовков и параграфов в красивый, удобный и интерактивный интерфейс.

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

Что такое CSS и как он работает?

CSS — это язык таблиц стилей. Его основная задача — сказать браузеру, как именно нужно отображать тот или иной HTML-элемент. Браузер читает ваш HTML-код сверху вниз, строит структуру документа (DOM), а затем применяет к ней правила CSS.

Синтаксис CSS прост и логичен. Он состоит из правил. Каждое правило имеет две основные части:

  • Селектор: указывает, какой элемент мы хотим изменить.
  • Блок объявлений: указывает, как мы хотим его изменить (набор свойств и значений).
  • В этом примере h1 — это селектор, а внутри фигурных скобок находятся объявления. Свойство color получает значение blue, а font-size — значение 24px.

    Селекторы: искусство выбора

    Чтобы применить стиль, нужно сначала точно «прицелиться» в нужный элемент. CSS предоставляет для этого мощный набор инструментов — селекторов.

    Основные виды селекторов

    Существует несколько базовых способов выбрать элемент:

    * Селектор по тегу: Выбирает все элементы с определенным именем тега. Например, p выберет все абзацы на странице. * Селектор по классу: Выбирает элементы, у которых есть определенный атрибут class. В CSS обозначается точкой. Например, .button выберет все элементы с классом button. Это самый часто используемый тип селектора, так как он позволяет гибко стилизовать группы элементов. * Селектор по идентификатору (ID): Выбирает единственный элемент с уникальным атрибутом id. В CSS обозначается решеткой. Например, #header выберет элемент с id="header". Используйте их с осторожностью, так как ID должен быть уникальным на странице. Универсальный селектор: Обозначается звездочкой . Он выбирает абсолютно все элементы на странице. Часто используется для сброса стандартных отступов браузера.

    !Иллюстрация работы различных CSS-селекторов на примере структуры веб-страницы

    Комбинаторы и вложенность

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

  • Пробел (потомок): div p выберет все абзацы p, которые находятся внутри div (на любом уровне вложенности).
  • Знак больше (дочерний элемент): div > p выберет только те абзацы, которые являются непосредственными детьми div.
  • Вес селекторов (Специфичность)

    Что произойдет, если к одному элементу применяются два противоречащих правила? Например, в одном файле написано, что текст красный, а в другом — синий. Браузер решает этот конфликт с помощью механизма специфичности.

    Представьте это как систему баллов:

    * Стили в атрибуте style (инлайн-стили) — самые сильные. * ID селекторы (#id) — очень сильные. * Классы (.class), псевдоклассы и атрибуты — средняя сила. * Теги (div, p) — самая слабая сила.

    Если специфичность одинакова, побеждает то правило, которое написано в коде ниже.

    Блочная модель (Box Model)

    Это, пожалуй, самая важная концепция для понимания размеров и отступов в CSS. Каждый элемент на веб-странице — это прямоугольный ящик (box). Даже если он выглядит круглым или имеет прозрачный фон, для браузера это все равно прямоугольник.

    !Визуализация блочной модели CSS, показывающая слои Content, Padding, Border и Margin

    Блочная модель состоит из четырех компонентов (изнутри наружу):

  • Content (Контент): Собственно содержимое элемента (текст, изображение).
  • Padding (Внутренний отступ): Пространство между контентом и границей. Фон элемента распространяется и на эту область.
  • Border (Граница): Рамка вокруг элемента.
  • Margin (Внешний отступ): Пространство между границей этого элемента и соседними элементами. Эта область всегда прозрачна.
  • Расчет размеров элемента

    Понимание того, как рассчитывается общая ширина элемента, критически важно для верстки. В стандартной модели (когда свойство box-sizing имеет значение content-box), если вы задаете элементу width: 100px, это ширина только контента.

    Формула полной ширины элемента в пространстве выглядит так:

    Где: * — полная ширина, занимаемая элементом на странице. * — ширина контента (заданная свойством width). * — левый и правый внутренние отступы (padding). * — толщина левой и правой границ (border). * — левый и правый внешние отступы (margin).

    Это часто вызывает путаницу: вы задали ширину 100 пикселей, добавили рамку и отступы, и вдруг элемент перестал помещаться в родительский контейнер.

    Свойство box-sizing

    Чтобы упростить жизнь разработчикам, существует свойство box-sizing: border-box. При его использовании значение width включает в себя и контент, и padding, и border. Это делает верстку гораздо более предсказуемой.

    > Большинство современных проектов начинают CSS с глобального сброса, устанавливая box-sizing: border-box для всех элементов.

    Позиционирование элементов

    По умолчанию элементы на странице располагаются в «нормальном потоке» (normal flow): блочные элементы (как div, p, h1) идут сверху вниз, занимая всю доступную ширину, а строчные (как span, a) — слева направо.

    Свойство position позволяет вырвать элементы из этого скучного порядка. Рассмотрим его значения:

    1. Static (Статичное)

    Это значение по умолчанию. Элемент находится в нормальном потоке. Свойства top, right, bottom, left и z-index на него не влияют.

    2. Relative (Относительное)

    Элемент остается в нормальном потоке, занимая свое законное место. Однако, вы можете сдвинуть его визуально относительно этого места, используя координаты top, left и т.д.

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

    3. Absolute (Абсолютное)

    Элемент полностью удаляется из нормального потока. Другие элементы ведут себя так, будто «абсолютного» элемента не существует — они занимают его место.

    Позиционирование происходит относительно ближайшего предка, у которого position не равно static. Если такого предка нет, элемент позиционируется относительно окна браузера (точнее, исходного содержащего блока).

    !Сравнение поведения элементов при относительном и абсолютном позиционировании

    4. Fixed (Фиксированное)

    Похоже на абсолютное, но элемент позиционируется относительно окна браузера (viewport). При прокрутке страницы такой элемент остается на месте. Это идеально подходит для закрепленных шапок сайта (sticky headers) или кнопок «Наверх».

    5. Sticky (Липкое)

    Гибрид relative и fixed. Элемент ведет себя как обычный (relative), пока пользователь не доскроллит до него. В этот момент он «прилипает» к указанной позиции (например, к верху экрана) и движется вместе с прокруткой, пока не закончится родительский блок.

    Работа с Z-Index

    Когда мы начинаем двигать элементы и накладывать их друг на друга (особенно при absolute и fixed), возникает вопрос: кто будет сверху?

    За это отвечает свойство z-index. Оно принимает целые числа (положительные, отрицательные или ноль). Элемент с большим z-index будет перекрывать элемент с меньшим z-index.

    Важно: z-index работает только для элементов, у которых position отличается от static.

    Заключение

    Мы рассмотрели три кита CSS: селекторы позволяют нам выбирать, что красить; блочная модель объясняет, как элементы занимают пространство; а позиционирование дает власть над расположением блоков. Эти знания — фундамент, на котором вы будете строить любые интерфейсы, от простых блогов до сложных веб-приложений. В следующих статьях мы углубимся в современные методы верстки, такие как Flexbox и Grid, которые делают процесс размещения элементов еще более гибким.

    2. Введение в JavaScript: синтаксис, типы данных и функции

    Введение в JavaScript: синтаксис, типы данных и функции

    Мы уже построили скелет сайта с помощью HTML и надели на него красивую одежду с помощью CSS. Но наш сайт всё ещё похож на манекен: он красивый, но неподвижный. Пришло время вдохнуть в него жизнь. В этом нам поможет JavaScript.

    В этой статье мы познакомимся с основами программирования на JavaScript (или просто JS). Мы разберем, как хранить данные, какие они бывают и как создавать собственные команды — функции.

    Что такое JavaScript?

    JavaScript — это язык программирования, который позволяет сделать веб-страницы интерактивными. Если HTML — это структура, а CSS — это стиль, то JavaScript — это поведение.

    С его помощью можно: * Обновлять контент без перезагрузки страницы. * Анимировать элементы. * Показывать всплывающие окна. * Проверять правильность заполнения форм. * Реагировать на клики, движения мыши и нажатия клавиш.

    > JavaScript не имеет ничего общего с языком Java, кроме похожего названия. Это два совершенно разных языка, как «ковер» и «коверкот».

    Переменные: коробки для данных

    Любая программа работает с данными: числами, текстом, списками. Чтобы компьютер запомнил какую-то информацию, её нужно положить в «коробку» и подписать эту коробку уникальным именем. В программировании такие коробки называются переменными.

    !Визуализация переменных как коробок с данными

    В современном JavaScript есть два основных способа создать переменную:

  • let — для переменных, значение которых может меняться.
  • const — для переменных, которые задаются один раз и навсегда (константы).
  • Раньше использовалось ключевое слово var, но сейчас оно считается устаревшим из-за некоторых особенностей поведения, которые могут привести к ошибкам.

    Типы данных

    В наши «коробки» можно класть разные вещи. В JavaScript существует несколько основных типов данных. Компьютеру важно знать тип данных, чтобы понимать, что с ними можно делать (например, числа можно складывать, а текст — нет).

    1. Числа (Number)

    Используются для любых математических вычислений. В JS нет разделения на целые и дробные числа — все они относятся к типу Number.

    С числами можно производить арифметические операции. Рассмотрим простую формулу расчета площади круга:

    Где: * — площадь круга. * — математическая константа (примерно 3.14). * — радиус круга.

    В коде это выглядело бы так:

    2. Строки (String)

    Это любой текст. Строки всегда должны быть заключены в кавычки. Можно использовать одинарные ', двойные " или обратные ` ` кавычки.

    3. Булевый тип (Boolean)

    Логический тип, который имеет всего два значения: истина (true) или ложь (false). Он используется для принятия решений (например: «Пользователь авторизован?» — Да/Нет).

    4. Null и Undefined

    Это два специальных типа, обозначающих «пустоту», но с разным смыслом:

    * undefined: «Значение не задано». Если вы создали переменную, но ничего в нее не положили, она будет undefined. * null: «Значение отсутствует». Это когда вы намеренно говорите, что здесь «ничего» нет.

    Функции: фабрика действий

    Если переменные — это существительные (данные), то функции — это глаголы (действия). Функция — это блок кода, который можно выполнить много раз в разных местах программы.

    Представьте функцию как мясорубку: вы кладете в неё мясо (входные данные), она что-то делает внутри, и выдает фарш (результат).

    !Принцип работы функции: входные данные, обработка, результат

    Объявление функции

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

    Здесь name — это параметр. Это переменная, которая будет доступна только внутри этой функции. Чтобы функция сработала, её нужно вызвать:

    Возврат значения (return)

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

    Когда интерпретатор JavaScript доходит до слова return, выполнение функции немедленно прекращается, и значение возвращается в то место, где функция была вызвана.

    Стрелочные функции

    В современном JavaScript существует более короткий способ записи функций — стрелочные функции.

    Они работают практически так же, но записываются компактнее и имеют некоторые отличия в работе с контекстом (о чем мы поговорим в продвинутых уроках).

    Операторы сравнения

    Чтобы программы могли принимать решения, нам нужно уметь сравнивать данные. Результатом сравнения всегда является булево значение (true или false).

    * > (больше), < (меньше) * >= (больше или равно), <= (меньше или равно) * === (строгое равенство) * !== (строгое неравенство)

    Важно: В JavaScript есть оператор == (нестрогое равенство) и === (строгое равенство). Всегда старайтесь использовать ===.

    * 5 == "5" вернет true (JS преобразует строку в число). * 5 === "5" вернет false` (типы данных разные: число и строка).

    Заключение

    Сегодня мы заложили фундамент для работы с JavaScript. Мы узнали, как хранить информацию в переменных, какие бывают типы данных и как создавать собственные команды с помощью функций. Это базовый синтаксис, на котором строится вся логика веб-приложений.

    В следующей статье мы научимся соединять JavaScript с HTML и CSS, чтобы изменять содержимое страницы на лету и реагировать на действия пользователя. Мы погрузимся в работу с DOM (Document Object Model).

    3. Работа с DOM: манипуляция HTML-элементами и стилями через код

    Работа с DOM: манипуляция HTML-элементами и стилями через код

    Мы прошли долгий путь. Сначала мы создали структуру страницы с помощью HTML, затем придали ей стиль и красоту, используя CSS. В прошлой статье мы познакомились с синтаксисом JavaScript, узнали о переменных и функциях. Теперь пришло время объединить все эти знания.

    Представьте, что HTML — это стены дома, CSS — это обои и мебель, а JavaScript — это электричество и умная система управления. Но как именно «умный дом» узнает, что нужно включить свет или открыть шторы? Ему нужен интерфейс для взаимодействия с физическими объектами. В веб-разработке таким интерфейсом является DOM.

    В этой статье мы разберем, как JavaScript «видит» вашу страницу, как он может находить на ней элементы, менять их текст, цвет и даже создавать новые блоки из воздуха.

    Что такое DOM?

    Аббревиатура DOM расшифровывается как Document Object Model (Объектная Модель Документа). Когда браузер загружает вашу веб-страницу, он не просто рисует картинку на экране. Он берет ваш HTML-код и превращает его в сложную древовидную структуру объектов, которая хранится в оперативной памяти.

    Для JavaScript каждый тег, каждый кусочек текста и каждый атрибут — это объект, у которого есть свои свойства и методы. Благодаря DOM, JavaScript получает полный доступ к содержимому страницы.

    !Схематичное изображение DOM-дерева, показывающее иерархию элементов веб-страницы

    Глобальным объектом, который открывает вход в эту структуру, является document. Если вы напишете это слово в консоли браузера, вы увидите всю вашу страницу.

    Поиск элементов: как найти иголку в стоге сена

    Прежде чем что-то изменить, это «что-то» нужно найти. В DOM существует несколько способов поиска элементов. Мы рассмотрим самые современные и удобные.

    querySelector и querySelectorAll

    Это универсальные солдаты поиска. Они используют те же селекторы, что и CSS. Если вы умеете писать CSS-селекторы, вы уже умеете искать элементы в JS.

  • document.querySelector(selector): Возвращает первый найденный элемент, соответствующий селектору. Если элемент не найден, вернет null.
  • document.querySelectorAll(selector): Возвращает все найденные элементы в виде списка (коллекции).
  • Примеры:

    Устаревшие методы

    Вы можете встретить в старом коде такие методы, как getElementById, getElementsByClassName или getElementsByTagName. Они работают быстрее, но менее гибки. В современной разработке querySelector стал стандартом де-факто благодаря своему удобству.

    Манипуляция содержимым

    Нашли элемент? Отлично. Теперь давайте изменим его содержимое. Для этого у DOM-элементов есть специальные свойства.

    innerHTML

    Это свойство позволяет получить или изменить HTML-содержимое внутри элемента. Вы можете вставить туда не просто текст, а целую разметку с тегами.

    > Будьте осторожны с innerHTML! Если вы вставляете туда текст, полученный от пользователя, злоумышленники могут внедрить вредоносный скрипт. Это называется XSS-атакой.

    textContent

    Это более безопасный способ. Он работает только с текстом. Если вы попытаетесь вставить теги через textContent, они отобразятся как обычный текст, а не как HTML-разметка.

    Работа со стилями

    JavaScript позволяет менять внешний вид элементов на лету. Существует два основных подхода: прямое изменение стилей и работа с классами.

    Прямое изменение через свойство style

    У каждого DOM-элемента есть объект style. Свойства в нем соответствуют CSS-свойствам, но пишутся в формате camelCase (верблюжий регистр), так как дефис в JavaScript означает вычитание.

    * CSS: background-color -> JS: backgroundColor * CSS: font-size -> JS: fontSize * CSS: margin-top -> JS: marginTop

    Этот способ добавляет стили прямо в атрибут style тега (инлайн-стили), что перебивает почти любые правила в CSS-файле.

    Управление классами через classList

    Более профессиональный подход — заранее описать классы в CSS, а через JavaScript просто переключать их. Это разделяет ответственность: CSS отвечает за вид, а JS — за логику.

    У свойства classList есть удобные методы:

    * element.classList.add('class-name') — добавляет класс. * element.classList.remove('class-name') — удаляет класс. * element.classList.toggle('class-name') — добавляет класс, если его нет, и удаляет, если он есть. * element.classList.contains('class-name') — проверяет наличие класса (возвращает true или false).

    Создание и удаление элементов

    Иногда нам нужно не просто изменить существующий элемент, а создать новый. Например, добавить комментарий пользователя в список или показать уведомление.

    Алгоритм создания элемента выглядит так:

  • Создаем элемент: Используем метод document.createElement(tagName).
  • Наполняем его: Добавляем текст, классы или стили.
  • Вставляем на страницу: Находим родителя и помещаем в него наш новый элемент.
  • Методы вставки

    * parent.appendChild(node): добавляет элемент в конец родителя. * parent.prepend(node): добавляет элемент в начало родителя. * parent.before(node): вставляет элемент перед родителем (на том же уровне). * parent.after(node): вставляет элемент после родителя.

    Удаление элементов

    Чтобы удалить элемент, достаточно вызвать у него метод remove().

    Геометрия элементов и вычисления

    Иногда для создания сложной анимации или интерфейса (например, прогресс-бара чтения статьи) нам нужно знать точные размеры элементов или позицию прокрутки. DOM предоставляет нам числовые значения размеров.

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

    Формула расчета процента прокрутки выглядит следующим образом:

    Где: * — искомый процент прокрутки (от 0 до 100). * — текущая прокрутка по вертикали (получаем через window.scrollY). * — полная высота всего документа (получаем через document.documentElement.scrollHeight). * — высота видимой части окна браузера (получаем через document.documentElement.clientHeight).

    Почему мы вычитаем высоту окна из высоты документа? Потому что, когда мы доскроллили до самого низа, верхний край окна находится не в конце документа, а на расстоянии одной высоты экрана от конца.

    !Иллюстрация параметров прокрутки страницы для расчета прогресса чтения

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

    Заключение

    DOM — это мощный инструмент, который превращает статичную верстку в живое приложение. Мы научились находить элементы, менять их текст и стили, создавать новые блоки и даже рассчитывать их положение.

    Однако, все изменения, которые мы делали в примерах выше, происходили мгновенно при запуске скрипта. Настоящая магия начинается тогда, когда эти изменения происходят в ответ на действия пользователя: клик мышкой, нажатие клавиши или прокрутку страницы. В следующей статье мы разберем События (Events) — механизм, который позволяет запускать наш код именно в нужный момент.

    4. События и интерактивность: обработка кликов и ввода данных

    События и интерактивность: обработка кликов и ввода данных

    В предыдущих статьях мы научились создавать структуру страницы с помощью HTML, стилизовать её через CSS и даже манипулировать элементами, используя JavaScript и DOM. Но до сих пор наши страницы оставались «немыми». Они не реагировали на действия пользователя. Если вы нажимали на кнопку, ничего не происходило. Если вы вводили текст в форму, он просто оставался там.

    Сегодня мы вдохнем настоящую жизнь в наши интерфейсы. Мы разберем тему событий (Events). Именно события превращают статичный документ в полноценное приложение, которое откликается на каждое движение мыши и нажатие клавиши.

    Что такое событие?

    Событие — это сигнал от браузера о том, что что-то произошло. Браузер постоянно следит за всем: движением курсора, прокруткой колесика, нажатием клавиш на клавиатуре, изменением размеров окна и даже окончанием загрузки картинок.

    Когда происходит одно из этих действий, браузер генерирует событие. Наша задача как разработчиков — «поймать» этот сигнал и выполнить определенный код в ответ. Этот код называется обработчиком события (event handler) или слушателем (event listener).

    Представьте, что вы ждете важный звонок. Телефон (браузер) звонит (генерирует событие), и вы (скрипт) поднимаете трубку и говорите «Алло» (выполняете функцию-обработчик).

    Способы назначения обработчиков

    Существует несколько способов сказать браузеру: «Эй, если пользователь кликнет сюда, запусти эту функцию». Давайте рассмотрим их эволюцию от худшего к лучшему.

    1. Использование HTML-атрибутов (Не рекомендуется)

    Самый старый способ — прописать обработчик прямо в HTML-теге.

    Почему это плохо? Потому что мы смешиваем структуру (HTML) и поведение (JavaScript). Это нарушает принцип разделения ответственности. Если у вас будет 100 кнопок, вам придется писать этот код 100 раз. Поддерживать такой код очень сложно.

    2. Использование DOM-свойства (Допустимо, но с ограничениями)

    Мы можем назначить обработчик через свойство элемента в JavaScript.

    Это уже лучше, так как HTML остается чистым. Однако у этого способа есть серьезный недостаток: одному событию можно назначить только один обработчик. Если вы напишете btn.onclick еще раз ниже, он перезапишет предыдущий.

    3. addEventListener (Рекомендуемый стандарт)

    Это самый современный и гибкий способ. Метод addEventListener позволяет вешать сколько угодно обработчиков на одно и то же событие.

    Синтаксис выглядит так:

    * event — название события (строка), например 'click'. Обратите внимание: без приставки on. Не 'onclick', а просто 'click'. * handler — функция, которая сработает при наступлении события.

    Пример:

    В этом примере при клике на кнопку выполнятся обе функции. Это дает огромную гибкость при разработке сложных интерфейсов.

    Объект события (Event Object)

    Когда происходит событие, браузер не просто вызывает вашу функцию. Он передает в неё специальный аргумент — объект события. Этот объект содержит массу полезной информации о том, что именно произошло.

    Обычно этот аргумент называют event или просто e.

    Отмена действий браузера по умолчанию

    Многие элементы имеют встроенное поведение. Например: * Клик по ссылке <a> переводит на другую страницу. * Нажатие кнопки submit в форме отправляет данные на сервер и перезагружает страницу.

    Часто нам нужно предотвратить это поведение, чтобы обработать действие самостоятельно через JavaScript (например, отправить форму без перезагрузки через AJAX).

    Для этого используется метод event.preventDefault().

    Распространение событий: Всплытие (Bubbling)

    Это одна из самых важных и часто непонятных концепций для новичков. Представьте, что у вас есть такая структура HTML:

    Если вы кликнете на кнопку button, вы одновременно кликнете и на div.card (потому что кнопка внутри него), и на div.section (потому что карточка внутри него), и даже на body.

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

    !Визуализация процесса всплытия события от целевого элемента к родительским.

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

    Иногда всплытие нужно остановить. Для этого у объекта события есть метод event.stopPropagation(). Но используйте его осторожно, так как это может нарушить работу аналитики или других скриптов на странице.

    Делегирование событий

    Понимание всплытия позволяет использовать мощный паттерн — делегирование.

    Представьте, что у вас есть список из 100 задач.

    Вы хотите, чтобы при клике на задачу она зачеркивалась. Можно найти все 100 элементов li и каждому добавить addEventListener. Но это:

  • Затратно для памяти браузера (100 функций-обработчиков).
  • Неудобно, если вы добавите новую задачу динамически — на неё придется вешать обработчик отдельно.
  • Вместо этого мы вешаем один обработчик на родителя (ul). Благодаря всплытию, клики по li дойдут до ul.

    В этом коде мы используем event.target, чтобы понять, где именно произошел клик. Это и есть делегирование: родитель «делегирует» обработку событий своим детям.

    Основные типы событий

    Событий в браузере сотни, но в 90% случаев вы будете работать со следующими группами:

    События мыши

    * click: одиночный клик левой кнопкой. * contextmenu: клик правой кнопкой (вызов контекстного меню). * mouseover / mouseout: курсор наведен на элемент / ушел с элемента. * mousedown / mouseup: кнопка мыши нажата / отпущена.

    События клавиатуры

    Они обычно вешаются на поля ввода или на весь документ (document).

    * keydown: клавиша нажата (срабатывает при удержании). * keyup: клавиша отпущена.

    В объекте события при этом доступны свойства event.key (значение символа, например, "Enter" или "a") и event.code (физический код клавиши).

    События форм

    Работа с формами — основа интерактива.

    * submit: попытка отправки формы. * focus: элемент получил фокус (пользователь кликнул в поле ввода). * blur: элемент потерял фокус. * input: значение в поле изменилось (срабатывает мгновенно при каждом нажатии). * change: значение изменилось и зафиксировано (срабатывает, когда пользователь закончил ввод и убрал курсор).

    Пример «живого» поиска:

    Удаление обработчиков

    Иногда обработчик нужно убрать. Например, кнопка должна сработать только один раз. Для этого используется метод removeEventListener.

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

    Если бы мы написали btn.addEventListener('click', function() { ... }), мы бы не смогли удалить этот обработчик, так как у функции нет имени, и мы не можем на неё сослаться.

    Заключение

    События — это нервная система вашего веб-приложения. Они связывают действия пользователя с логикой вашего кода. Мы изучили, как подписываться на события через addEventListener, как использовать объект события для получения деталей и как работает механизм всплытия.

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

    5. Создание динамического интерфейса: анимации и изменение классов на лету

    Создание динамического интерфейса: анимации и изменение классов на лету

    В предыдущих статьях мы прошли большой путь: от создания статической разметки до обработки кликов пользователя. Теперь наш сайт умеет реагировать на действия, но эти реакции часто выглядят резкими и неестественными. Элементы появляются мгновенно, цвета меняются скачком. В реальном мире так не бывает — предметы имеют инерцию, они двигаются плавно.

    В этой статье мы научимся делать интерфейсы живыми и приятными для глаза. Мы разберем, как правильно управлять стилями через JavaScript, как создавать плавные переходы с помощью CSS и как запускать сложные анимации, когда пользователь взаимодействует со страницей.

    Управление классами: правильный подход

    В статье про DOM мы уже касались свойства style, которое позволяет менять CSS-свойства напрямую. Например, element.style.display = 'none'. Однако в профессиональной разработке этот метод используется редко. Почему?

  • Смешивание логики и оформления: JavaScript должен отвечать за поведение, а CSS — за внешний вид. Когда вы пишете стили внутри JS, вы нарушаете это разделение.
  • Сложность поддержки: Если вы захотите изменить цвет активной кнопки, вам придется искать его в JS-коде, а не в CSS-файле.
  • Приоритет стилей: Инлайн-стили (которые добавляет JS) перебивают почти всё, что написано в CSS, что может привести к трудноуловимым багам.
  • Использование classList

    Лучший способ изменить внешний вид элемента — это заранее описать состояние в CSS-классе, а через JavaScript просто добавить или убрать этот класс. Для этого используется свойство classList.

    Представьте, что у нас есть выпадающее меню. Вместо того чтобы менять его height или display через JS, мы создадим класс .open.

    Теперь в JavaScript нам достаточно одной строчки:

    Это делает код чистым и понятным. Вся визуальная магия остается в CSS.

    CSS Transitions: магия плавности

    Простое переключение классов меняет стили мгновенно. Чтобы изменение происходило плавно, в CSS существует свойство transition (переход). Оно говорит браузеру: «Не меняй значение сразу, а растяни это изменение во времени».

    !Визуализация процесса плавного перехода от одного состояния элемента к другому

    Анатомия перехода

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

    Свойство transition — это сокращенная запись для четырех свойств:

  • transition-property: Имя свойства, которое нужно анимировать (например, opacity, width или all для всех).
  • transition-duration: Длительность анимации (в секундах s или миллисекундах ms).
  • transition-timing-function: Функция времени (закон ускорения). Например, linear (равномерно), ease-in (медленный старт), ease-out (медленный финиш).
  • transition-delay: Задержка перед началом анимации.
  • Расчет времени анимации

    Иногда важно точно знать, когда анимация полностью закончится, чтобы запустить следующее действие в JavaScript. Полное время, которое пройдет от момента добавления класса до завершения движения, можно выразить формулой:

    Где: * — общее время до окончания анимации. * — время задержки перед стартом (значение transition-delay). * — время активной фазы анимации (значение transition-duration).

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

    CSS Animations: сложные сценарии

    transition отлично подходит для простых переходов от состояния А к состоянию Б (например, при наведении мыши). Но что, если нам нужно, чтобы элемент сначала подпрыгнул, потом покрутился, а потом исчез? Или чтобы он пульсировал бесконечно?

    Для этого используются Keyframes (ключевые кадры).

    Правило @keyframes

    Сначала мы определяем сценарий анимации в CSS:

    Здесь мы сказали: в начале (0%) элемент на месте, в середине (50%) он сдвинут вверх на 20 пикселей, в конце (100%) снова на месте.

    Применение анимации

    Теперь применим этот сценарий к элементу:

    Свойство animation имеет множество параметров, включая animation-iteration-count (сколько раз повторять, infinite — бесконечно) и animation-direction (например, alternate для движения туда-обратно).

    Взаимодействие JavaScript и CSS-анимаций

    Самый мощный паттерн — это запуск CSS-анимации с помощью JavaScript. Например, при успешной отправке формы мы хотим показать зеленую галочку.

  • Создаем CSS с анимацией.
  • В JS при наступлении события добавляем класс.
  • Важный момент: нужно знать, когда анимация закончилась, чтобы, например, удалить элемент из DOM.
  • Для этого существуют специальные события:

    * transitionend: срабатывает, когда завершился transition. * animationend: срабатывает, когда завершилась animation.

    Это критически важно для производительности. Если вы просто скроете элемент визуально (прозрачность 0), он останется в DOM и будет занимать память. Удалять его сразу нельзя — анимация не успеет проиграться. Событие animationend решает эту проблему.

    Анимация через JavaScript: requestAnimationFrame

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

    Раньше для этого использовали setInterval, но это плохая практика, так как она не синхронизирована с частотой обновления экрана монитора, что вызывает рывки.

    Современный стандарт — метод requestAnimationFrame(callback). Он говорит браузеру: «Перед следующей перерисовкой экрана выполни эту функцию».

    Пример плавной анимации

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

    Позиция элемента в момент времени при равномерном движении описывается формулой:

    Где: * — текущая координата по оси X. * — начальная координата. * — скорость движения (пикселей за кадр). * — количество прошедших кадров (или времени).

    В коде это выглядит как рекурсивный вызов:

    Этот метод обеспечивает максимально плавную анимацию (обычно 60 кадров в секунду) и экономит батарею ноутбуков и телефонов, так как останавливается, если вкладка не активна.

    Оптимизация производительности

    При создании анимаций важно помнить, что не все CSS-свойства «дешевы» для браузера. Браузер тратит разные ресурсы на отрисовку разных изменений.

  • Дешевые свойства (можно анимировать смело): transform (перемещение, вращение, масштаб) и opacity (прозрачность). Они обрабатываются видеокартой (GPU).
  • Дорогие свойства (избегайте их анимации): width, height, top, left, margin. Изменение этих свойств заставляет браузер пересчитывать геометрию всей страницы (Reflow), что вызывает тормоза на слабых устройствах.
  • > Всегда старайтесь использовать transform: translate(...) вместо изменения top или left для перемещения элементов.

    Заключение

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

    Мы научились: * Переключать классы через classList для изменения состояний. * Использовать transition для простых переходов. * Создавать сценарии через @keyframes. * Слушать события окончания анимации animationend. * Использовать requestAnimationFrame для сложных JS-анимаций.

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