• Тормоза браузера из-за стилей, решение?

    sfi0zy
    @sfi0zy Куратор тега CSS
    Creative frontend developer
    Для начала для нас важно осознать, что у разных фильтров разная вычислительная сложность. Они не все "плохие". Алгоритмы для brightness, grayscale, hue-rotate и других манипуляций с цветом выполняются за O(1) для каждого пикселя. Т.е. нагрузка на железо растет линейно в зависимости от площади элемента на экране. Это не так страшно. А вот фильтры размытия, blur или drop-shadow, имеют сложность где-то в районе O(R^2). Там есть разные варианты оптимизаций, но в среднем мы говорим именно о квадратичной зависимости от радиуса размытия. И это для каждого пикселя. Именно отсюда мы имеем сильные тормоза при попытке что-то большое размыть на пол экрана. Дохлые видеокарты телефонов и ноутбуков не вывозят. Браузеры не умеют такие вещи переиспользовать, так что это переразмытие происходит снова и снова, и мы имеем что имеем.

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

    В контексте верстки тут есть полтора варианта, что можно сделать. Можно рассчитывать такие вычислительно-сложные штуки еще при разработке и загружать в страницу сразу в виде картинок или видео. Это не идеальный вариант, пропорции получаются фиксированные, но иногда подходит. Есть вариант рассчитывать такие штуки в фоне на WebGL. Т.е. мы грузим интерфейс, смотрим какого там все размера получается, и один раз в фоновом режиме генерируем картинки нужного размера и потом плавно показываем. Такой вариант частенько встречается в рекламно-конкурсных проектах, когда за прелоадером в начале скрывается в том числе и такая генеративная история. Тут мы получаем гибкость в плане размеров и хорошую производительность сайта в целом, потому что все операции проходят только один раз, а дальше у нас все переиспользуется в виде обычных картинок. Каких-то принципиально других вариантов у нас пока нет. Только дизайн менять.
    Ответ написан
    3 комментария
  • Как лучше всего сверстать такую необычную секцию?

    delphinpro
    @delphinpro Куратор тега CSS
    frontend developer
    Ничего интересного не вижу.
    Вижу сетку 3х3 с вариативными размерами ячеек.
    Легко реализуется и адаптируется на гридах.
    Возможно сетку нужно будет сделать более детальную:
    spoiler
    642a4bcce1146926923977.png
    Ответ написан
    Комментировать
  • TS как вывести массив типов параметров из массива дженериков?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    type ExtractGenerics<T extends readonly unknown[]> = T extends readonly []
      ? []
      : T extends readonly [G<infer V>, ...infer Next]
        ? [V, ...ExtractGenerics<Next>]
        : never;
    
    function unwrap<C extends readonly G<unknown>[]>(containers: C) {
      return containers.map(container => container.value) as ExtractGenerics<C>
    }

    https://www.typescriptlang.org/play?#code/C4TwDgpg...
    Ответ написан
    2 комментария
  • Как сделать анимацию кардиограммы?

    sfi0zy
    @sfi0zy Куратор тега CSS
    Creative frontend developer
    Вообще рисование линий обычно делается через изменение свойств stroke-dasharray и stroke-dashoffset у кривых в SVG. Это самый простой способ в рамках фронтенда, хотя и изначально эти вещи были для другого придуманы. Но в случае с ЭКГ нужна постоянная скорость рисования по горизонтали. Поэтому можно взять прямоугольную маску в рамках той же SVG, и двигать ее в сторону:

    Ответ написан
    6 комментариев
  • Как разбить строку на массив с учетом разделителя?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    может, наивно добавить квадратные скобки в строку?
    const line = '1, "221,21", "dssds", 555, "dfgfdgfdg, dd"';
    const row = JSON.parse(`[${line}]`);
    // Array(5) [ 1, "221,21", "dssds", 555, "dfgfdgfdg, dd" ]
    Ответ написан
    2 комментария
  • Как применить стили дочерным классам в зависимости их количества?

    Ankhena
    @Ankhena Куратор тега CSS
    Нежно люблю верстку
    Может, вам поможет обычный css и селектор типа
    :nth-child(3):last-child {
      тут стили, если третий является последним
    }
    Ответ написан
    Комментировать
  • Как правильно такое сверстать?

    hahenty
    @hahenty
    ('•')
    Ограничение в фиксированных ширине и количестве табов.
    Ответ написан
    Комментировать
  • Как проверить передан ли в параметр функции event?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Попробовать так и сяк
    function func(mixedData) {
      const id = mixedData?.target?.id ?? mixedData;
      console.log(id);
    }
    
    func(123) // 123
    func({target: {id: 456}}) // 456

    Что это было?!
    ?.optional chaining
    ??Nullish coalescing operator

    Но это всё не фэн-шуёво, не аккуратненько как-то.
    Лучше бы функции строго принимать один тип параметра — ожидать только id.
    А что-то поменять при вызовах.
    Ответ написан
    6 комментариев
  • Как сделана проекция надписи "Россия мы c табой!" на вирусном видео?

    Сделана в After Effects.

    Помимо озвученной критики, дополню: длина ролика ровно 10 секунд.
    Ответ написан
    5 комментариев
  • Как суммировать целые кратные 3 и 5 до указанного числа?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Повторяющийся момент, вычисление суммы последовательности от 0 до N с шагом — в функцию.

    Сложить ряд с шагом 3, ряд с шагом 5 и вычесть места, где они пересекаются и значения двоятся: в кратных 15 – тоже ряд, с шагом 15.
    const sum = number => {
      if (number < 0) return 0;
    
      // вспомогательная функция считает сумму ряда с шагом step
      const sequenceSum = step => {
        const q = Math.floor(number / step);
        return q * (q + 1) * step / 2;
      }
    
      return sequenceSum(3) + sequenceSum(5) - sequenceSum(3 * 5);
    }
    
    sum(18) // 78
    Ответ написан
    Комментировать
  • От чего могут быть артефакты на тостере в Chrome?

    Поставил в хром расширение, через которое можно налету менять стили сайта - "Stylish"

    Добавил через него:
    .question_short {
         transform-style: inherit;
    }

    и все стало нормально. У разработчиков пока ресурсов нет на исправление этого косяка.
    Ответ написан
    Комментировать
  • Как лучше поступать в такие моменты по bem?

    SeaInside
    @SeaInside
    15 лет пилю все эти штуки
    Эта разметка абсолютно правильная в двух случаях:
    1) Ваши `close` и `card` действительно нигде не переиспользуются;
    2) Объём стилей блока `some-class` остаётся адекватным для восприятия.

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

    Возьмём разметку посложнее (не надо в ней искать какого-то смысла, просто от фонаря что-то набрал для иллюстрации):
    <div class="block">
      <!-- Header -->
      <div class="block__header">
        <h2 class="block__title">Title</h2>
        <div class="block__actions">
          <button type="button" class="block__action block__action--edit">
            <span class="block__action-icon"></span>
          </button>
        </div>
      </div>
      <!-- Content -->
      <div class="block__content">
        <p>...</p>
      </div>
      <!-- Footer -->
      <div class="block__footer">
        <div class="block__about">
          <div class="block__author"></div>
          <div class="block__date"></div>
        </div>
        <div class="block__awards">
          <div class="block__award">
            <div class="block__award-inner"></div>
            <div class="block__award-tooltip">
              <div class="block__award-tooltip-content"></div>
              <button type="button" class="block__award-tooltip-close"></button>
            </div>
          </div>
        </div>
      </div>
    </div>


    Положим, что весь контент этого блока уникальный и никак не переиспользуется.
    Объём стилей `block` при такой структуре неизбежно станет некомфортным для восприятия, строк на 200-300.

    В таком случае хорошо создать внутренний блок (или несколько) просто для того, чтобы размазать сложность.
    `block-header`, `block-footer` или даже `block-footer-award`.

    Самое главное здесь организовать файловую структуру / конфигурационный файл / чем вы там ещё собираете таким образом, чтобы было очевидно, что `block-footer` - это не самостоятельный блок, а внутренний блок `block`, нужный только для упрощения восприятия, и он не может / не должен использоваться в отрыве от него (в этом случае у него не должно быть в названии общего префикса с `block`, чтобы не создавать путаницу)

    * И не забывать о том, что даже для таких внутренних блоков действуют те же самые правила, что и для других - вся внешняя геометрия задаётся через элементы.
    Ответ написан
    8 комментариев
  • Зачем в теге script код обернут в комментарий?

    Stalker_RED
    @Stalker_RED
    В прошлом тысячелетии были браузеры, которые не понимали тег <script> и отображали его содержимое на странице. Потому содержимое тегов <script> было принято комментировать, чтобы не пугать пользователя.
    Зачем это продолжают делать в opencart в 2022 - неведомо, возможно дань традиции.
    Ответ написан
    1 комментарий
  • Как написать функцию которая возвращает класс в зависимости от параметра?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Ответ написан
    Комментировать
  • Как нарисовать плавные струйки дыма?

    DarkWood
    @DarkWood
    Я опишу вам алгоритм, который позволит создать в Illustrator нечто похожее. Подойдет ли оно вам - смотрите сами. Автоматизировать этап создания кривых - крайне сложно. Думаю, из описания сами поймете почему.

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

    61802664abff2460020473.png

    Создаете между ними бленд (Ctrl+Alt+B) с дистанцией в 1 пиксель. Можно поставить меньше - тогда переходных кривых будет больше. При толщине контура в 1 пиксель меньше 0.4 пикселя ставить уже особого смысла не будет.

    618026a380abc845121510.png

    Не переживайте, что всё слилось в одноцветье. Кстати, желаемый цвет вы можете задать как сейчас, так и на следующем этапе. Рекомендую делать это как раз там.

    На всякий случай скопируйте бленд (Ctrl+C > Ctrl+F), чтобы была возможность что-то исправить, если последующий результат не понравится.

    Выполните команду Object> Blend> Expand.

    Далее Shift+Ctrl+G

    Задаете малую непрозрачность (около 10%). Как раз сейчас лучше всего менять цвет. Можете также поменять режим смешивания.

    618026b345bc8360746368.png

    Ctrl+G.

    Большее свечение на "петлях" можно сделать дубликатом этой группы (Ctrl+C > Ctrl+F). Эту копию тоже надо будет потом разгруппировать (Shift+Ctrl+G) изменить цвет на более светлый, непрозрачность и режим смешивания по вкусу.

    618026de13dcb347638107.png

    Собственно, узор готов.

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

    618026e910192073261890.png

    Продолжение такое же: Shift+Ctrl+G, меняете прозрачность, режим смешивания и т.п.

    618027083db5a504901276.png

    Можно добавить еще одну кривую цвета фона и переплести ее с остальными. Можно переплетать два бленда от основного цвета к цвету фона и т.д. и т.п.

    Все команды, кроме рисования кривых, прекрасно записываются в экшен.
    Ответ написан
    2 комментария
  • Почему у переменной тип unknown?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    Во-первых, infer в самом предикате участвует как any
    Во-вторых, функция с меньшим количеством аргументов является подтипом для функции с большим количеством аргументов (это позволяет, например, отдать в колбэк функцию, которая не использует всех переданных ей аргументов)

    То есть тип () => void является потомком типа (param: any) => void, а значит Ваш предикат в типе A становится истинным и уходит в ветку, где Вы возвращаете R из infer, который выводится к вершине иерархии - типу unknown

    То что Вы задумали, можно сделать так:
    type A<T> = T extends (...param: infer P) => void
      ? P extends [infer R, ...unknown[]]
        ? R
        : string
      : string;
    Ответ написан
    1 комментарий
  • Как реализовать такой блок?

    Ankhena
    @Ankhena Куратор тега CSS
    Нежно люблю верстку
    1 комментарий
  • Как сделать такой элемент при наведений?

    Ankhena
    @Ankhena Куратор тега CSS
    Нежно люблю верстку
    Поскольку у ссылок есть иконки и они, вероятно, будут сделаны с помощью псевдо, то подумала, что нужно придумать решение с помощью только одного псевдоэлемента. Да и вообще, раз можно одним, то зачем писать два..



    код

    <nav>
      <ul>
        <li><a href="">link</a></li>
        <li><a href="">link</a></li>
        <li><a href="">link</a></li>
        <li><a href="">link</a></li>
        <li><a href="">link</a></li>
      </ul>
    </nav>


    nav {
      width: 200px;
      background: #92aef4;
    }
    
    ul {
      --color: white;
      --radius: 30px;
      --smoothing-radius: 29.4px;
      border-right: 10px solid var(--color);
      padding: 0 0 2em 1em;
      list-style-type: none;
    }
    
    a {
      position: relative;
      display: block;
      padding: 0.5em;
      border-radius: var(--radius) 0 0 var(--radius);
      text-decoration: none;
      color: #6704f2;
    }
    
    a::before {
      content: "❄ ";
      color: white;
    }
    
    a:hover::before {
      color: deeppink;
    }
    
    a:hover {
      background: var(--color);
    }
    
    a:hover::after {
      content: "";
      position: absolute;
      right: 0;
      top: 50%;
      transform: translateY(-50%);
      width: var(--radius);
      height: calc(100% + 2 * var(--radius));
    }
    
    li:not(:last-child):not(:first-child) a:hover::after {
      background: radial-gradient(at top left, transparent var(--smoothing-radius), var(--color) var(--radius)) no-repeat top right / var(--radius) var(--radius),
        radial-gradient(at bottom left, transparent var(--smoothing-radius), var(--color) var(--radius)) no-repeat bottom 0 right 0 / var(--radius) var(--radius);
    }
    
    li:first-child a:hover::after {
      background: radial-gradient(at bottom left, transparent var(--smoothing-radius), var(--color) var(--radius)) no-repeat bottom 0 right 0 / var(--radius) var(--radius);
    }
    
    li:last-child a:hover::after {
      background: radial-gradient(at top left, transparent var(--smoothing-radius), var(--color) var(--radius)) no-repeat top right / var(--radius) var(--radius);
    }
    body {
      padding: 50px;
      margin: 0;
      font-size: 20px;
      font-family: 'Neucha', cursive;
      background: #eee;
    }

    Ответ написан
    Комментировать
  • Как сделать такого рода эффект?

    sfi0zy
    @sfi0zy Куратор тега CSS
    Creative frontend developer
    не могу найти в поиске

    SVG-маски, маски с помощью clip-path в CSS, маски на канвасе, маски в шейдерах, и.т.д. В общем гуглите все, что связано со словом "маска". Вариант с шейдерами самый производительный, с SVG - самый простой.

    Пример с SVG:


    Пример с шейдерами (не совсем такой, но для передачи идеи пойдет):
    Ответ написан
    Комментировать