Під капотом: перетягування, дотики та CSS-каскад

Створення панелі інтерфейсу, розмір якої можна змінювати, складніше, ніж здається. Вам доводиться одночасно керувати макетами, подіями дотику та правилами CSS.

Ось три технічні уроки з мого нещодавнього редизайну інтерфейсу візуального порівняння (visual-diff UI).

1. Припиніть використовувати ширину вікна для макетів

Не використовуйте window.innerWidth, щоб визначити, чи є ваш макет вертикальним або горизонтальним. Якщо користувач змінить розмір вікна, ваша логіка зламається.

Замість цього використовуйте фактичний стан CSS. Використовуйте getComputedStyle, щоб перевірити flex-direction. Це зчитує реальне значення після застосування всіх медіазапитів. Це гарантує, що ваша логіка перетягування відповідає тому, що користувач бачить насправді.

2. Обробляйте події дотику та миші разом

Щоб перетягування працювало як на десктопах, так і на мобільних пристроях, вам потрібен уніфікований підхід.

  • Використовуйте опціональний ланцюжок (optional chaining) для отримання координат. Це дозволяє одній функції обробляти як події миші, так і події дотику.
  • Використовуйте { passive: false } для touchmove. Браузери за замовчуванням роблять події дотику пасивними (passive), щоб полегшити прокручування. Якщо ви не встановите це значення на false, ви не зможете викликати e.preventDefault(). Без цього виклику сторінка буде прокручуватися під час спроби перетягування.
  • Прив'язуйте слухачі подій move та end до document. Якщо користувач занадто швидко проведе пальцем, він може вийти за межі розділювача. Прив'язка до document гарантує, що перетягування триватиме, навіть якщо вказівник зміститься.

3. Уникайте конфліктів із системою видимості

Я зіткнувся з багом специфічності CSS. У мене був один клас для приховування панелей і інший для встановлення напрямку макета.

Проблема:

  • .view-panel { display: none; }
  • .diff-layout { display: flex; }

Оскільки вони мали однакову специфічність, перемагав той, що був останнім у файлі. Це означало, що мої панелі залишалися видимими навіть тоді, коли вони мали бути прихованими.

Виправлення: Ніколи не дозволяйте допоміжному класу макета встановлювати властивість display. Нехай це робить клас видимості.

Замість: .diff-layout { display: flex; flex-direction: column; }

Використовуйте: .view-panel.diff-layout { flex-direction: column; }

Це підвищує специфічність і гарантує, що клас макета змінює лише напрямок, а не видимість.

Source: https://dev.to/bonzai2carn/under-the-hood-drag-touch-and-css-cascade-in-a-real-diff-ui-1b66