Масштабируемый способ обработки определений шрифтов в приложении React.js

Обычно в моем коде есть несколько разных шрифтов, которые я использую с некоторыми вариантами вроде:

  • Arial, font-weight: 400, font-style: normal
  • Arial, font-weight: 400, font-style: italic
  • Arial, font-weight: 700, font-style: normal
  • Helvetica, font-weight: 400, font-style: normal
  • Helvetica, font-weight: 400, font-style: italic

Я использую для этого CSS-IN-JS-библиотеку styled-components, поэтому не использую некоторые styles.css. Иногда дизайнер приходит ко мне и просит изменить, например. Arial до Comic Sans для font-style: italic; и font-weight: 400;

Это не может быть код путем простой замены в кодовой базе проекта, так как существуют другие варианты этого шрифта.

Я хочу свести к минимуму объем работы, необходимой для включения этого изменения, поэтому необходимо изолировать эти объекты шрифтов в одном месте.

ВОПРОС:

Я разработал 3 подхода для этого, и 3-й, по-видимому, лучший, но, пожалуйста, дайте советы по своему опыту. Может быть, есть некоторые дополнительные минусы или плюсы для каждого из указанных ниже?

ПОДХОДЫ:

Первый подход

Я думал об извлечении этих текстовых определений в отдельный style-components, например:

const ArialGeneral = styled.span`
  font-family: Arial;
  font-style: normal;
  font-weight: 400;
`

const ArialNormal = styled(ArialGeneral)``
const ArialNormalItalic = styled(ArialGeneral)`
  font-style: italic;
`

И затем обертывание всех текстовых вхождений соответствующим стилем.

...
<HeroText>
  <ArialNormal>
    Welcome to our system!
  </ArialNormal>
</HeroText>
...

Против:

  • Дополнительные теги JSX

  • Возможно, некоторые вычислительные затраты на повторное предоставление этих дополнительных компонентов вместе с вычислениями CSS браузером

Плюсы:

  • У меня будет 1 место для управления всеми вхождениями какой-либо данной комбинации [font-family, font-style, font-weight]

Второй подход

Используйте ту же технику, но вместо определения styled-component используйте глобальный styles.css с теми же определениями в виде классов, например:

.font-arial-normal {
  font-family: Arial;
  font-style: normal;
  font-weight: 400;
}

Для этого потребуется украсить текстовые элементы некоторыми классами, например:

...
<HeroText className="font-arial-normal">
  Welcome to our system!
</HeroText>
...

Минусы:

  • Использование двух форматов CSS-in-JS и styles.css

  • Добавление classNames в JSX

Плюсы:

  • В отличие от варианта 1 не потребуются ресурсы для дополнительной компиляции JSX

  • То же преимущество, что и в варианте 1

Третий подход

Я вижу в этой статье WebType Лучшие практики использования шрифтов-весов, а также в примерах для пакетов веб-шрифтов, которые я загружаю, каждая комбинация [font-family, font-style, font-weight] определяется как отдельный шрифт, например как в этом примере из упомянутого ресурса (предположим, что все это font-style: normal;):

{ font-family: "Interstate Light"; font-weight: normal; }
{ font-family: "Interstate Medium"; font-weight: normal; }
{ font-family: "Interstate Regular"; font-weight: normal; }
{ font-family: "Interstate Semibold"; font-weight: bold; }
{ font-family: "Interstate Bold"; font-weight: bold; }
{ font-family: "Interstate Extrabold"; font-weight: bold; }
{ font-family: "Interstate Black"; font-weight: bold; }

Минусы:

  • Требуется больше начальной работы (но эти пакеты webfont уже предоставляют необходимые css).

Плюсы:

  • Мы больше не используем fonts.css, где мы определяем шрифты (я использую это во всех вариантах), тем самым устраняя проблемы using two formats CSS-in-JS and styles.css второго метода

  • Может использоваться в JS-IN-CSS, поскольку я использую его сейчас, а замена кодовой базы изменит только те шрифты (чего я пытаюсь достичь), так что те же преимущества, что и в варианте 1

Ответ 1

Я думаю, что самое важное, на что вам нужно ответить, - это варианты вариантов шрифтов в вашем приложении. Они глобальны? Вам нужны только их для определенных тегов (т.е. h1, h2 и т.д.)? Вам нужны конкретные переопределения, характерные для нескольких компонентов?

По моему опыту, вы обычно объявляете только 1 или 2 шрифта для каждого приложения, и обычно они обычно являются приложениями. Его редкость, что я вижу эти шрифты, которые используются очень конкретно (например, 1 или 2 элемента с определенным классом или идентификатором) и скорее имеют тенденцию размещаться на body.

Первый подход

Предполагая, что используются только одно семейство шрифтов (т.е. "Arial", "open sans" и т.д.), первый подход будет очень трудно масштабировать. Как вы уже упоминали, это не только создает много шума, но если вы назовете компонент после имени шрифта, он быстро устареет с момента переключения семейств шрифтов. Это потребует немалых изменений для вашего приложения. Я не рекомендую этот подход, если вам не нравится редактировать много файлов, когда приходит время для обновления.

Второй подход

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

Третий подход

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

Альтернативный подход

Я считаю, что подход @font-face в паре со стилизованным компонентом injectGlobal API будет получать вам самый большой пробег (они даже упомяните @font-face в документах!)

Перемещение семейств шрифтов означает обновление вашего определения @font-family и обновление вашего объявления font-family за один раз. Еще лучше, вы избегаете файлов .css и сохраняете все в стиле-компонентах!

Опять же, предполагая, что ваша цель - настроить шрифт на весь экран, возможно, вариант на теге или два (h2, h2 и т.д.), это позволяет делать все ваши изменения в одном месте и Я считаю, что лучше всего творит свою цель.

Взгляните на документацию @font-face, чтобы получить представление о стилях шрифта, если вы не знакомы с ним, Я знаю, что есть много ресурсов, чтобы помочь вам объявить @font-face (если вы уже не используете что-то вроде шрифтов Google).

Ответ 2

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

const General = styled.span`
  ... // other properties
  font-family: ${ props => props.theme.fontFamily };
  font-style: ${ props => props.theme.fontStyle };  
  font-weight: ${ props => props.theme.fontWeight };
`

В отношении третьего подхода мы можем иметь комбинацию [font-family, font-style, font-weight]. Компонент behavoiur зависит от комбинации, переданной в качестве опоры на нее.

let arialNoraml300 = { 
  fontFamily: Arial,
  fontStyle: normal,
  fontWeight: 300
};

let helveticaOblique900 = { 
  fontFamily: Helvetica, 
  fontStyle: oblique, 
  fontWeight: 900 
}

... // other combinations

Его можно использовать как <General theme={arialNoraml300} /> или <General theme={helveticaOblique900} />

Если мы попросили какое-либо изменение, нам нужно заменить комбинацию, переданную компоненту.

Надеюсь, он вам поможет.

Ответ 3

Возможно, вы можете использовать css и .extend для решения этой проблемы?

DEMO

import styled, { css } from 'styled-components';

const apply = (tag, styles) => {
  return styled[tag]`${styles}`.extend
};

// BASE STYLES

const arial400 = css`
  font-family: Arial;
  font-weight: 400;
`;

const arial400italic = css`
  ${arial400};
  font-style: italic;
`;

const helveticaNormal = css`
  font-family: Helvetica;
  font-weight: normal;
`;

const helveticaItalicBold = css`
  ${helveticaNormal};
  font-style: italic;
  font-weight: bold;
`;

const HeroText = apply('h2', arial400italic)`
  color: red;
`;

const FancyButton = apply('button', helveticaItalicBold) `
  color: white;
  background: indigo;
  padding: 10px;
`;

...

<div>
  <HeroText>Welcome to our system!</HeroText>
  <FancyButton>CLICK ME</FancyButton>
</div>

...

Другой подход?

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

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

Плюсы:

  • используя странную apply функцию вместо классического стиля.

Минусы:

  • нет необходимости добавлять теги JSX
  • одно место для глобальных стилей, которое может легко расширять друг друга
  • поскольку глобальные стили по-прежнему являются "стилизованными компонентами", что означает, что вы можете использовать реквизиты
  • легко расширить существующие стили, все, что вам нужно, просто заменить styled.tag на apply('tag', baseStyles)

Ответ 4

Я не совсем согласен с вышеизложенными плюсами и минусами. Большинство из них связаны с CSS и CSS-IN-JS. CSS отлично подходит для стилизованных компонентов. Правило большого пальца - использовать CSS для общих классов и компонентов стиля для тематики и переменных. Используйте все, что вы чувствуете, менее неудобно и обслуживаемо.

Приступая к вашей конкретной проблеме сохранения шрифтов и изменений шрифта и веса.

Я сталкивался с подобными проблемами несколько раз.

Платформы с поддержкой тем, итерацией дизайна или даже в hackathons.

В основном вы меняете их с одинаковым языком дизайна на верхнем уровне. т.е. полностью изменить основной шрифт и вес в приложении.

Итак, ваши шрифты определяются с помощью @font-face с первичным, вторичным, третичным и т.д. вместо конкретного имени шрифта, так как вам придется изменять только определение, а не только имена классов.

   @font-face {
     font-family: "primary-default";
     font-weight:  regular
     src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2"),
          url("/fonts/OpenSans-Regular-webfont.woff") format("woff");
   }

Если вам нужно изменить первичный-умолчанию, чтобы иметь другое семейство шрифтов и вес, вы можете соответствующим образом изменить эти определения.

Если это только определенные изменения или быстрые переопределения, используйте вспомогательные классы

 .primary-fontStyle {
   font-family: "primary-default";
   font-weight:  regular
 }