Vue-FAQ
919 subscribers
556 photos
90 videos
548 links
Канал сайта https://vue-faq.org
Информация о Vue.js, фронтенд разработке и не только

Contacts: @RuslanMakarov
Download Telegram
HTML5 и CSS3. Аккордеон.

Фронтендерам за свою жизнь много раз приходится делать "аккордеоны", и каждый раз это какой-то челендж с велосипедами, своими или чужими. Хороший аккордеон нельзя было сделать без JavaScript.

В HTML5 появились тэги details и summary:

<details>
<summary>Title</summary>
<p>Some description</p>
</details>


Они позволяют построить элемент "аккордеон" на чистом семантическом HTML, без привлечения JS. Переключение видимости происходит атрибутом open. Следить за состоянием можно подписавшись на событие toggle.

На vue-faq.org используются именно details для организации вопросов-ответов.

По умолчанию данный элемент выглядит как на картинке, с треугольным маркером, однако details и summary допускают глубокую стилизацию, позволяя оформить аккордеон как понадобится - например, убрать маркер, добавить поворачивающийся крестик и анимацию при раскрытии. Соответствующий CSS - в комментариях.

#tip #html
HTML5 и CSS3 - достаточно функциональные языки и могут делать сами многое, для чего раньше нужно было задействовать JavaScript

В этой статье приводится 5 примеров элементов на чистом HTML/CSS

1. Toggle
2. Автоподсказки в инпуте (datalist)
3. Color picker
4. Accordion (details)
5. Dialog

#tip #html #css
HTML и CSS - языки программирования.

Доказано.

Пример мини-калькулятора, складывающего два числа, заданных в двоичном формате, на чистом HTML и CSS.

#css #html #pl
Недавно получилось сваять прото-калькулятор для сложения двух чисел на чистом HTML + CSS, и тут попадается реализация игры Wordle тоже только на HTML + CSS.

Вообще, HTML5 и CSS3 - довольно функциональные языки. В веб-програмировании обычно всё, что можно реализовать на них (в первую очередь - анимации), лучше делать на них, чтобы разгрузить JavaScript и улучшить производительность приложения, читаемость кода и поддерживаемость проекта.

Два вышеуказанных примера в это "обычно", естественно, не входят.

#tip #html #css
На конференции Google I/O был озвучен новый функционал, который стал доступен веб разработчикам в 2023-2024 годах:

HTML and CSS
The inert attribute
Size container queries and container query units
New color spaces and functions
The :user-valid and :user-invalid pseudo-classes
CSS Subgrid
Trigonometric functions in CSS
CSS :has() selector
Complex nth-child selectors in CSS with the 'of S' syntax
New range syntax for media queries
The linear() easing function
CSS Nesting
Relaxed parsing for CSS Nesting
Lazy-load offscreen iframes
Declarative Shadow DOM
CSS offset-position and offsetpath values
The Popover API
align-content on block layout

JavaScript and Web APIs
Import maps
modulepreload
Offscreen canvas
Constructable stylesheets
Compression streams
The Origin Private File system
Array fromAsync() static method
ArrayBuffer transfer() and transferToFixedLength()
groupBy() functions
Promise.withResolvers
intl.Segmenter

Видеообзор

#google #html #css #js
Задача:

Есть тяжелый сайт. Надо для хорошего UX показать какой-нибудь сплэш-скрин (глобальный прелоадер) в самом начале и отключить его после загрузки всех (по возможности) ресурсов и готовности сайта

Как это сделать без JS?

Задача имеет минимум два решения - через CSS и через HTML

#challenge #css #html
По задаче выше

Сплэш-скрин (стартовая заставка) значительно улучшает UX. Во Vue он ставится в index.html и отключается в onMounted() App.vue

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

CSS

Например, прилетит стиль (или в конце html файла, или css файла)

.splash-screen {
display: none;
}


Ещё вариант подсказали в комментариях - через :has(). Возможны и другие способы.

HTML

Интересней с HTML. Для этого можно использовать Declarative Shadow DOM (часть Web Components), который позволяет строить Shadow DOM без JS. У Shadow Root есть слоты. Слот будет показывать дефолтное значение ( в нашем случае блок на весь экран с лоадером), пока не прогрузится <div slot="splash-screen">, который его затрет.

<template shadowrootmode="open">
<slot name="splash-screen">
<div class="splash-screen">Loading...</div>
</slot>
</template>

<!-- additional content -->

<div slot="splash-screen">
<div />
</div>


#challenge #css #html
Когда-то модалки были довольно нетривиальным элементом, породившим кучу библиотек для их отображения (даже сам когда-то заэнпиэмил одну).

Сейчас HTML <dialog> делает это легко и непринужденно

Вот пример модалки в 30 строк с оверлеем, закрытием по outside клику и клавише ESC, с поддержкой доступности и других W3C стандартов

<script setup lang="ts">
import { ref } from "vue";

const dialog = ref(null);

function show() {
dialog.value.showModal();
}
function close() {
dialog.value.close();
}

function onClick($event) {
if ($event.target === dialog.value) {
dialog.value.close();
}
}

defineExpose({ show, close });
</script>

<template>
<dialog
ref="dialog"
role="textbox"
tabindex="0"
@mousedown="onClick"
>
<slot />
</dialog>
</template>

<style scoped></style>


Использование:

const holaModal = useTemplateRef("holaModal");

// holaModal.value.show();
...
<ModalDialog ref="holaModal">
<div>Hola!</div>
<button @click="holaModal.close()">
Close
</button>
</ModalDialog>


И всё. Не надо никаких композаблов, телепортов и мучений с позиционированием.

В комментариях будут стили для плавного (fade in-out) открытия и закрытия окна диалога и оверлея.

#html #tip
Раскрывающиеся аккордеоны удобно делать через стандартный details HTML элемент.

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


<details name="some-group">
<summary>1</summary>
<p>…</p>
</details>
<details name="some-group">
<summary>2</summary>
<p>…</p>
</details>
<details name="some-group">
<summary>3</summary>
<p>…</p>
</details>


Также details поддерживает хорошую стилизацию - пример
(Небольшая часть этого работает пока только в Chromium)

#html #accordion
Что-то захотелось редактируемый профиль пользователя на странице сделать через html contenteditable

Потратил кучу времени, что-то получилось, но в итоге переделал на input

Очень неудобно, особенно с системой байндинга и реактивности Vue
Не делайте так.

#html
В мой vite-plugin-html-injection сделали первый PR

Приятно, чёрт возьми.

Теперь во фрагментах можно использовать Vite env переменные, типа %VITE_API_URL%, которые будут заменены на их значения.

#vite #plugin #lib
Если нужно добавить на страницу поле для редактирования текста, можно использовать атрибут contenteditable, как более приятную замену textarea (для полей больших форм это не очень хорошая замена).

Чтобы ограничить ввод только текстом, можно использовать значение plaintext-only у атрибута contenteditable. Это предотвратит вставку HTML-разметки, картинок или стилей.

<div 
contenteditable="plaintext-only"
data-placeholder="Начните печатать..."
></div>

Дополнительно можно ловить события input и paste, чтобы очищать текст от случайного форматирования. Например, при вставке можно заменить HTML-содержимое на обычный текст через e.clipboardData.getData('text/plain').

Подробнее о тонкостях работы с contenteditable в статье на web.dev

#html