Стоит ли с помощью js вычислять размеры элементов?
Пишу сайт с полностью резиновым интерфейсом. То есть сайт масштабируется в зависимости от ширины экрана, так как размеры практически всех элементов заданы через vw. Мне очень нравится данный подход, так как сайт выглядит практически идентично на всех устройствах (речь идёт о десктопах, ноутбуках и планшетах, с телефонами отдельный разговор). Но есть определённые проблемы, а именно иногда при определённых обстоятельствах появляются некоторые баги, к примеру может быть два блока вроде как с одинаковым размером (например 10vw в ширину), но по факту один блок больше другого на 1px. Я выявил некоторые зависимости для появления этих багов и способы борьбы с ними. К примеру почти во всех случаях помогает хитрое применение backface-visibility. Но как вы знаете это свойство способно вызывать довольно серьёзную нагрузку на устройство, особенно в моём случае, так как интерфейс очень насыщенный и имеет большое количество анимаций. Я стремлюсь сделать интерфейс сайта похожим на интерфейсы нативных приложений. Приходится очень профессионально балансировать на грани красота/качество/производительность и всегда искать наилучшие компромиссы.
Сейчас собираюсь осваивать vue.js и переводить сайт полностью на него. Таким образом появляется множество интересных возможностей. Например я смогу вместо использования единиц vh, vw просчитывать все размеры элементов интерфейса прямо на месте при каждом изменения размеров окна в пикселях. Думаю это избавит меня от множества неприятных проблем и развяжет руки в выборе различных вариантов вёрстки.
Собственно вопрос в том, применяется ли вообще где-то такой подход? Можно ли глянуть на какие-то примеры? Нет ли в данном способе каких-то существенных недостатков? Мб для реализации такого функционала есть какие-то готовые инструменты или подходы?
Не думаю, что у меня возникнут какие-то серьёзные проблемы с реализацией данной задумки, но всё же хотелось бы услышать чужое мнение по данному вопросу.
P.S: Хочу заметить, что сайт является SPA, то есть все размеры будут вычисляться исключительно только при запуске сайта и при изменение размеров окна одновременно с рендерингом самого SPA как такового.
P.S.S: Более того есть идея хранить в local storage результат предыдущего вычисления размеров и ширину экрана, которая была использована для этого. Таким образом, если размер окна не будет изменяться, то этот просчёт вообще произойдёт всего один раз.
Александр Фёдорцев: да мне тут честно говоря толком то даже никто и не объяснил почему вдруг должно тормозить. Это SPA, то бишь просчёт будет выполняться всего лишь один раз за сеанс и всё)) Ну хоть убей, не понимаю почему должно тормозить. Это от силы лишних 100ms при запуске, а дальше никаких проблем. Никаких relayout'ов не будет, с чего бы им быть. Перепросчётов при появлении новых элементов никаких не предполагается.
Что вас не устраивает в результате работы vw? Что-то съезжает? Всё таки наличие лишнего пикселя это скорее всего следствие математики и того, что пиксели целочисленные. И если перекладывать это на js предыдущие 2 фактора не изменятся. Собственно, я веду к тому, что не помешает упрощённый пример на фидле, в котором видна проблема.
Константин Громов: не, боюсь это не реально. Баг довольно редко возникает и только при очень определённых обстоятельствах. Воспроизвести сложно. Но я почти на 100% уверен, что знаю из за чего он. Баг возникает, когда слой заданный в vh или vw переходит на собственный gpu слой. Например во время анимации. И собственно говоря видимо на gpu эти размерности просчитываются иначе (к примеру округляются в другую сторону). Так что работа с px
и просчётом на js точно решает эту проблему (в скрипте я уж точно смогу всё округлить как надо), а "n px" и в Африке "n px".
LordGuard: В ситуации когда ширина 1001px, а блоки по 50vw у обоих получается по 500.5px, но округлить оба само собой вы не сможете. Если это просто разница в 1 пиксель, то не стоит обращать внимания (например те же прицелы в играх из-за чётности пикселей на экране не указывают точно в центр и это не катастрофично). Но если же 1 пиксель сдвигает сетку это, возможно, из-за смешивания различных единиц (vw с px в одном ряду). Если не то и не то, тогда стоит рассматривать проблему детально для полного решения, и здесь нужен пример. Ну и конечно, если вы полностью уверены, что можно решить это javascript'ом, то делайте. На производительность это практически не повлияет.
Константин Громов: то есть выходит что при вынесение на отдельный gpu значение vw и vh округляется в большую сторону всегда, а обычные элементы округляются до ближайшего значения.. Из вот из за этого и возникает проблема...
LordGuard: Да, нечто похожее. Только здесь дело судя по всему не в GPU, а в коде который занимается обработкой свойств. Я давно где-то читал, что элементы у которых есть transform обрабатываются иначе и, видимо, ими занимается отдельный движок с другим подходом к округлению. Вашу проблему в конкретном случае можно решить перенеся псевдо-элемент с белым фоном на элемент .SpecialOffer, тогда лишний пиксель будет обрезаться overflow: hidden.
Константин Громов: ну вообще да, можно придумывать различные обходы данной проблемы, но в результате она возникает не тут, а где-то ещё. И честно говоря меня этот баг уже задолбал.
LordGuard: я тоже встретился с таким косяком, но я сделал проще - я фон блока сделал бэкграундом внутреннего блока (чтобы визуально не отличались).
При том такой баг - только в хроме происходит. Верно?
xmoonlight: проблема в том, что у меня этот баг всплывает далеко не в одном месте и всегда при разных обстоятельствах и в некоторых случая обойти его значительно сложнее
LordGuard: У меня есть подозрение, что писать обработчик на javascript'е задолбает не меньше. Плюс "баг довольно редко возникает и только при очень определённых обстоятельствах" я бы не стал морочится и просто оставил багрепорт гуглу.
xmoonlight: впринципи я так понимаю подход может быть такой. Выношу стили размеров всех элементов в style блок с тими же vh, vw. При старте js быстренько парсит этот блок и заменяет все значения vh и vw на соответствующие правильно округлённые значения в пикселях.
LordGuard: Насчёт того, что я писал изначально про 2 блока по 50vw и 1001px. Если писать обработчик самому, то такие ситуации придётся тоже обрабатывать. Ведь простой заменой будет неверно, а чтобы было правильно нужно как-то извернуться. Подобные вещи всегда всплывают при дублировании, казалось бы, несложного низкоуровневого функционала.
Этот вариант не подходит, так как у меня не "Адаптивный дизайн" как это принято понимать обычно, а именно что "резиновый". Есть, к примеру, блок который должен быть 10% от ширины экрана. Так вот он должен быть таким абсолютно всегда, а не от 8% до 12%..
sim3x: это никак не решается media запросами. Через media запросы можно лишь задать несколько вариантов размеров, но блок в таком случае будет иметь разное соотношение своих размеров к размерам окна, что не есть хорошо конкретно в моей концепции интерфейса. И скажите, пожалуйста, почему это блоку не надо иметь размер в %? Вы дизайнер?
Андрей Б.: это да, но если нужно сделать абсолютно все зависящим от ширины окна, то приходится использовать vw, процентами тут не отделаешься. А vw в свою очередь порождает множество неприятных багов.
Андрей Б.: vue при том что сайт будет рендериться на стороне пользователя и не будет такой фигни, что сайт сначала загрузится с одними размерами, а потом размеры пересчитаются и всё перескочит, что крайне неприятно выглядит. То есть можно будет совместить рендер самого DOM с рендерингом стилей размеров элементов.
Андрей Б.: представьте себе интерфейс компьютерной игры. Там как раз таки практически всегда применяется описанный мной подход к дизайну интерфейса. Не в техническом плане, а в том, что интерфейс полностью резиновый, а не "адаптивный". Так почему бы не применять такой подходит и в веб дизайне. Тем более, что у меня не новостной сайт. А SPA - браузерная игра.
Раньше - из-за зоопарка браузерных движков.
Сейчас из-за зоопарка разрешений и размеров экранов.
Допустимо только если:
Бьетесь бьетесь и никак не можете без этого решить.
Нужно быстро пофиксить.
Нет ресурсов времени/заказчик плохо оплачивае и хочется быстро и дешево сделать видимость
П.С.
И это все еще даже без учета того, что инструменты лучше использовать по назначению.
К такому решению приходил очень долго. Около года. Если делать несколько брейкпоинтов, даже достаточно много, то на специфических разрешениях будет не так как хотелось бы.
А вот в зоопарке разрешений и размеров экранов не вижу серьёзных проблем. Естественно я отдельно учту планшеты и телефоны. То есть я уверен, что на всех устройствах всё будет выглядеть правильно.
То есть я готов искать другое решение, но только при таком варианте судя по всему всё будет выглядеть именно так как надо.
И это не говоря о том какая еще фантазия у производителей может выйти в продажу.
Вы выбрали нестандартный путь, что приведет в увеличение себестоимости работ как сейчас так и при дальнейшей поддержке проекта.
или к уменьшению гарантий идентичности/адекватности отображения на различных девайсах.
dinegnet: проект я разрабатываю для себя, ни на кого не работаю. Времени у меня много. Я готов протестировать и отладить сайт на всех популярных устройствах. В общем спешки никакой нет и реализую я этот вариант более чем работоспособно, в этом я уверен. Хотя честно говоря не вижу каких либо предпосылок чтобы на retina экранах что-то не работало.
LordGuard: проект для себя - не повод не экономить свое время на дальнешей поддержке. особенно когда проект наскучит.
я вон уже лет 6 не могу свой личный сайт починить.
dinegnet: Через пару тройку лет возможно я просто уберу этот скрипт и верну vh, vw, т. к. кое-кто наконец-то нормально пофиксит chrome... (надеюсь). Не вижу серьёзных проблем в этом плане.
Да и проект предполагает неплохой профит. Думаю поддержка более чем окупится.
dinegnet: Вы уж выбирайте. "Фикс на тяп-ляп" или "нет другого выхода". Я другой выход уже год ищу параллельно с разработкой. Постоянно думаю на эту тему.
В лучшем случае - всё будет просто дико тормозить (особенно в контексте того что вы игру собираетесь делать). Получение размеров из js приводит к принудительному relayout, что всегда плохо.
Вообще трудно представить себе такой интерфейс, который нельзя сверстать используя современные технологии (flex/grid/.../calc/...). Пара скриншотов явно не помешала бы.
Почему же дико тормозить? Неужели просчёт всего DOM это не проблема для всяких vue.js, react и т. д., а просчёт нескольких сотен css кода внезапно становится большой проблемой? Это же будет происходить лишь при запуске игры, 1 раз. Сразу все стили.
LordGuard: конечно проблема, на эту тему написан миллиард статей, кроме того авторы и контрибьюторы react бьются над тем, чтобы уменьшить операции с DOM внутри react. Вы не сможете посчтитать размеры невидимых карточек правильно, т.е. при изменении интерфейса необходимо будет просчитывать что-то ещё. Проблема не в CSS/DOM, а в том, что перед получением значений из DOM будет перерисовка экрана, что плохо сказывается на производительности
Николай: эм, мне кажется вы не понимаете мой вариант решения проблемы. Я просто беру за основу ширину окна (при загрузке сайта/при изменение размера окна) и только в зависимости от него просчитываю style блок с размерами абсолютно всех элементов на сайте. Когда на сайте будет что-то изменяться стили не будут просчитываться заново и из DOM ничего запрашиваться тоже не будет. Все просчёты будут исключительно при запуске и при изменение окна. Всё.