Найти в Дзене
Как вычислить разницу между датами в javascript?
Представим что нам нужно вычислить разницу между двумя датами и показать результат в днях, часах, минутах и секундах. Можно воспользоваться специализированной библиотекой для работы со временем, например moment.js, или понять как это работает и написать свой код. 1. Сначала вычислим разницу между двумя датами в секундах, пускай это будут даты 1 января и 20 февраля: const startDate = new Date("Jan 1, 2025 00:00:00").getTime(); const endDate = new Date("Feb 20, 2025 00:00:00").getTime(); const...
4 месяца назад
​​Как использовать адаптивные изображения в HTML? Рассмотрим типичный сценарий - в шапке каждого поста установлена картинка, для экрана компьютера она узкая и длинная, например 1200x200 пикселей, а для экрана смартфона 320x200 пикселей. Если использовать большую картинку и просто обрезать лишнее на экране смартфона, например с помощью object-fit, то получим низкую скорость загрузки страницы. Идеально иметь несколько версий изображения и загружать только одно для каждого устройства. Чтобы устранить эту проблему, добавим в <img> атрибуты srcset и sizes. Они представляет собой набор значений, разделенных запятыми. Каждое значение srcset содержит url-изображения и дополнительные параметры(дескрипторы), каждое значение sizes содержит медиа запрос и минимальный размер картинки: <img src="small-image.png" alt="A description of the image." srcset="small-image.png 480w, large-image.png 800w" sizes="(max-width: 600px) 480px, 800px" > Атрибуты srcset и size выглядят сложными, но их не так уж сложно понять, если отформатировать их, как показано выше. Srcset определяет набор изображений, которые мы разрешаем браузеру выбирать, а также размер каждого изображения, обратите внимание, что здесь используется единица измерения w, а не пиксели. Sizes определяют набор медиа-условий (например, ширину экрана) и указывают, какой размер изображения лучше всего выбрать, когда определенные медиа-условия верны. Браузер определит первое истинное выражение в sizes, проверит размер указанный в нем и загрузит изображение из списка srcset, которое имеет тот же размер, или первое изображение, которое больше выбранного размера. Типичный Веб Разработчик
10 месяцев назад
​​Как отключить обновление страницы свайпом в мобильных браузерах? Обновление свайпом — популярная функция обновления страницы в мобильных браузерах. Однако в некоторых случаях мы хотели бы отключить это поведение по умолчанию. Сделать это можно с помощью свойства CSS overscroll-behavior. Как видно из названия, это свойство позволяет изменить поведение по умолчанию при чрезмерной прокрутке контейнера. Обновление свайпом можно отключить с помощью свойства CSS overscroll-behavior: body { overscroll-behavior: contain; } Установка overscroll-behaviour: contain отключает передачу прокрутки в родительский элемент — то есть сверхпрокрутка содержится только внутри самого элемента. Установка этого параметра в <body> предотвратит передачу чрезмерной прокрутки в браузере и, таким образом, предотвратит действие для обновления. Однако обновление по запросу происходит вертикально, и в некоторых случаях нам бы хотелось, чтобы по умолчанию прокрутка выполнялась в горизонтальном направлении (на странице может быть слайдер или карусель с событиями пролистывания влево-вправо). Это можно сделать с помощью overscroll-behavior-y: body { overscroll-behavior-y: contain; } Типичный Веб Разработчик
10 месяцев назад
​​Ускоряем написание HTML разметки с помощью Emmet в VSCode Emmet - это утилита, которая позволяет значительно ускорить ваш рабочий процесс с HTML. Просто введите любой тег без <> и нажмите TAB, в результате получите полноценную HTML разметку с обязательными атрибутами и закрывающим тегом. Рассмотрим популярные сокращения: 1. Вводим ! и нажимаем TAB, далее происходит магия и мы получаем разметку целой страницы. 2. Вводим html, получаем: <html> 3. Добавляем несколько братских элементов - h1+h2+p+btn, получаем: <h1></h1> <h2></h2> <p></p> <button></button> 3. Добавляем дочерние элементы - table>tr>td: <table> <tr> <td></td> </tr> </table> 4. Умножение - ul>li*3: <ul> <li></li> <li></li> <li></li> </ul> Это лишь часть возможностей Emmet. Изучайте и становитесь продуктивнее. Ссылки: YouTube | Дзен Дока Emmet
10 месяцев назад
Как анимировать меню c React Transition Group? Простая анимация меню на основе библиотеки React Transition Group за несколько минут. Ссылки: - YouTube | Дзен - Github Pet Project Типичный Веб Разработчик
10 месяцев назад
Ошибки при копировании объектов в JavaScript. И снова простая, на первый взгляд, задача имеет подводные камни о которых мало кто задумывается. Копирование объектов, что может быть проще: const someItemList = [ { name: 'Product 1', value: 'Some value 1' }, { name: 'Product 2', value: 'Some value 2' }, ] const newItemList = [...someItemList] Существует два типа копирования - поверхностное и глубокое. Первое работает быстро, и обычно его вполне достаточно, проблемы начинаются при копировании вложенных структур. Если изменить свойство объекта в новом массиве newItemList, то эти изменения будут видны и в исходном массиве someItemList. Причина - способ хранения данных, когда разные объекты ссылаются на одну ячейку памяти: console.log(someItemList[1] === newItemList[1]) // true Как решить данную задачу? Рассмотрим несколько вариантов: 1. Функция structuredClone() для глубокого копирования: const deep = structuredClone(someItemList) console.log(someItemList[1] === deep[1]) // false 2. Функция глубокого копирования из библиотеки утилит lodash: import cloneDeep from 'lodash.clonedeep' const deep = cloneDeep(someItemList) console.log(someItemList[1] === deep[1]) // false 3. Ещё один способ — сериализовать объект в JSON и распарсить его: const deep = JSON.parse(JSON.stringify(someItemList)) console.log(someItemList[1] === deep[1]) // false Типичный Веб Разработчик
10 месяцев назад
​​Как создать многостраничный сайт используя Vite? Vite - это инструмент сборки, созданный для обеспечения быстрого процесса разработки современных веб-проектов. Вы должно быть уже заметили что в проекте Vite, файл index.html является основным, так как во время разработки index.html - это точка входа (entry point) в ваше приложение. Получается, сборщик заточен на SPA или одностраничные приложения. Что делать, если нужно создать обыкновенный многостраничный сайт? Можем просто добавить нужные страницы в корень, такое решение будет работать, но только в режиме разработки. Но при сборке получаем только один файл index.html в папке dist. Здесь нет готовых решений из коробки. Придется немного почитать доку и ручками отредактировать файл vite.config.js. Для настройки нам понадобится список всех страниц нашего проекта в виде объекта: const pages = { index: resolve(__dirname, "index.html"), about: resolve(__dirname, "about.html"), team: resolve(__dirname, "team.html"), }; Передаем объект pages в build.rollupOptions и собираем проект еще раз. rollupOptions: { input: { ...pages, }, }, Теперь все страницы попали в папку для сборки dist. Видео: YouTube | Дзен Дока: https://vite-docs-ru.vercel.app/guide/build.html Типичный Веб Разработчик
10 месяцев назад
​​А вы используете Double Bang или Оператор двойной восклицательный знак (!!)? Сначала давай разберем что из себя представляет простой оператор восклицательный знак (!). Например, если выражения равны между собой, а мы хотим проверить что они не равны: console.log('string' === 'string'); // => true console.log('string' !== 'string'); // => false Таким образом мы просто инвертировали проверку. То же получим если поставим восклицательный знак перед выражением: const myString = "string"; console.log(!myString) // => false Здесь получаем нелогичный, на первый взгляд, результат, так как "не string", теоретически может быть чем угодно. Но javascript строго соблюдает правила, и сначала приводит "string" к true, а затем инвертирует его в false. Теперь будет проще понять что делает оператор двойной восклицательный знак: const checkIsTrue = (someVar) => { return !!someVar; }; Интерпретатор сначала вычисляет !someVar, а второй восклицательный знак переворачивает результат первого вычисления. Такой интересный способ позволяет нам всегда получать булевый результат. Любое значение будет преобразовано в булевый тип в соответствии с правилами приведения типов. Типичный Веб Разработчик
10 месяцев назад
​​Новые единицы измерения в CSS для решения старых проблем. Рассмотрим типичную проблему - в Safari адресная строка находится внизу окна, а кнопки навигации находятся под ней, и при этом в мобильной версии Chrome внизу окна располагаются кнопки навигации, а адресная строка висит сверху. Есть и другие менее популярные браузеры, где может быть все наоборот. Такое разнообразие добавляет трудностей при верстке. Если использовать только единицы vh, то элементы страницы будут распологаться без учета интерфейса браузера. Small Viewport Units (единицы измерения svh и svw) дают нам размеры, которые можно использовать для заполнения экрана, когда пользовательский интерфейс браузера максимально велик, а содержимое веб-сайта минимально. Large Viewport Units (единицы измерения lvh и lvw) дают размер, при котором пользовательский интерфейс браузера является наименьшим, а содержимое веб-сайта — наибольшим. По сути, lvh — это то, как действует модуль vh в настоящее время. Dynamic Viewport Units (единицы измерения dvh и dvw) дают динамические размеры области просмотра, это позволяет точно вписать верстку в область просмотра, независимо от размеров интерфейса браузера. И самое главное - данные единицы измерения поддерживаются всеми распространенными браузерами. Типичный Веб Разработчик
10 месяцев назад
Иммутабельность или неизменяемость состояния в ReactJS Состояние может хранить любые значения, включая объекты. Но мы не должны изменять объекты, которые хранятся в состоянии React, напрямую. Вместо этого, когда мы хотим обновить объект, нам нужно создать новый, и использовать его для обновления состояния. При работе с числами, строками и булевыми значениями, которые являются неизменными, мы просто обновляем состояние, например: setName("Dmitriy") при этом старое значение name заменяется на новое и происходит обновление компонента. А как быть с объектами? Технически, можно изменить содержимое самого объекта. Это называется мутацией: user.name = "Dmitriy" но это не приведет к нужному эффекту. Мы должны относиться к ним как к неизменяемым, как к числам, булевым и строкам. Вместо того чтобы изменять их, мы всегда должны заменять их. Надежный способ добиться нужного поведения — создать новый объект и передать его в setUser, при этом также копировать в него существующие данные, поскольку изменилось только одно поле name: setUser({ ...user, // Копируем все старые поля name: e.target.value, // Заменяем значение в поле name }); Типичный Веб Разработчик
10 месяцев назад
​​Как прижать футер к низу страницы с помощью CSS? Рассмотрим универсальный способ. Он не требует абсолютного позиционирования, вычислений с помощью функции calc() и работает во всех современных браузерах. Данный способ основан на CSS Flexbox и методе flex-grow. Таким образом центральный main элемент растет, занимает все свободное пространство и раздвигает соседние элементы header и footer. Дока по flex-grow: https://developer.mozilla.org/ru/docs/Web/CSS/flex-grow
11 месяцев назад
Как добавить изображению зеркальный эффект с помощью CSS? Что если можно переиспользовать одно изображение <img> несколько раз, например, если это изображение имеет зеркальную копию? Можно открыть графический редактор и сделать еще одну копию этого изображения, а можно использовать одну картинку, просто повернув её с помощью CSS. Для примера давай возьмем кнопки слайдера для перехода к следующему слайду (next) и возврату к предыдущему (prev). Используем одну картинку next-arrow.png для кнопки next-button, и просто зеркально разворачиваем эту картинку для кнопки prev-button. Типичный Веб Разработчик
11 месяцев назад