Less — это популярное языковое расширение для CSS, которое позволяет делать много интересных вещей, о которых CSS может только мечтать. Сверхспособности Less проистекают из трех новых возможностей, которых нет в CSS, а именно вложенности селекторов, переменных и миксинов. Less вместе с Sass выбил из колеи веб-стили, когда они были изобретены 10 лет назад, потому что это позволило разработчикам писать стили ближе к тому, как они пишут javascript.

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

Отличительной чертой React является то, что вы можете писать свой HTML вместе с вашим javascript, так что один компонент имеет весь соответствующий код вместе в одном месте. Styled-components — это альтернатива Less и Sass, использующая тот же способ организации. Теперь у вас могут быть составные части для вашего javascript, html и стилей, и вы можете написать все это, используя функции javascript. Это действительно лучший из миров!

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

Шаг 1. Установите глобальный стиль для всех глобальных таблиц стилей.

Мы берем любой глобальный стиль css и перемещаем его в глобальный стиль, обертывая его createGlobalStyle.

import { createGlobalStyle } from 'styled-components'

export const GlobalStyle = createGlobalStyle`
@font-face {
    font-family: "Roboto";
    font-weight: normal;
    src: local("Roboto"), url('https://fonts.google.com/...') format("truetype");
  }

  body {
      font-family: "Roboto", sans-serif;
      font-size: 12px;
      color: black;
  }

  h1 {
    font-size: 16px;
  }

  a {
      text-decoration: none;
      color: inherit;
  }

`

Затем, когда мы определили этот компонент <GlobalStyle />, мы добавляем его в корневой компонент нашего проекта:

const Layout = ({ children, title }) => (
  <>
    <GlobalStyle />
    <Header />
    <Page />
    </Footer>
  </>
)

Шаг 2. Переместите все переменные в стиль темы.

Styled-components предоставляет глобальный компонент темы, который вы можете определить в корне проекта, и он будет доступен везде. Допустим, это меньшее количество переменных, к которым мы хотим получить доступ для всего сайта:

@theme-text: #cccccc;
@label-theme: #2d5a6b;
@label-text: @theme-text;
@label-border: 1px solid @theme-text;

Мы создаем объект javascript с именем theme, в котором мы можем хранить все наши константы. Каждый ключ в объекте будет представлять имя переменной, а значением будет значение, в котором он находится меньше.

Однако проблема с объектами javascript заключается в том, что одно значение не может ссылаться на другое значение в одном и том же объекте. Поэтому, если у меня есть значение color и я хочу создать вторую переменную с именем backgroundColor, обратную color, мне не разрешено ссылаться на значение color, когда оно находится в том же объекте, что и переменная. место, где я его устанавливаю.

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

Итак, сначала мы преобразуем все наши переменные less в строки — будьте осторожны при переключении любых тире (-) на подчеркивание (_), потому что вы не можете использовать тире в имени переменной javascript. Когда мы создаем объект темы, мы можем иметь тире в имени ключа объекта, поэтому, если у нас есть переменная с именем less с именем @theme-text и мы хотим придерживаться нотации змеиного регистра во всех наших стилизованных компонентах, мы можем создав ключ theme-text в объекте theme: theme['theme-text']. Несколько строк кода стоят 1000 слов, поэтому я использовал следующий шаблон:

const color: '#442d6b';
const theme_text = '#cccccc';
const label_theme = '#2d5a6b';
const label_text = theme_text;
const label_border = `1px solid ${theme_text}`;


const theme = {
  color, //I don't need color: color here because the names are the same
  "theme-text": theme_text,
  "label-theme": label_theme,
  "label-text": label_text,
  "label-border": label_border
}

export default theme;

Теперь нам нужно импортировать объект темы в объект <ThemeProvider> в корне нашего проекта. Просто убедитесь, что мы экспортируем объект theme, а затем импортируем его в корень проекта и используем с компонентом <ThemeProvider> из библиотеки styled-components:

import { ThemeProvider } from 'styled-components'
import theme from './theme' //This is the theme object that we defined above

const Layout = ({ children, title }) => (
  <>
    <ThemeProvider theme={myTheme}>
      <GlobalStyle />
      <Header />
      <Page />
      </Footer>
    </ThemeProvider>
  </>
)

Теперь у нас будет доступ ко всему в объекте темы в качестве параметра во всех наших стилизованных компонентах, которые являются дочерними элементами <ThemeProvider>. Мы покажем вам, как это сделать в шаге 4, а затем мы должны показать вам, как скопировать остальные стили.

Шаг 3. Разбейте меньшее количество компонентов на фрагменты стилей, которые можно прикрепить к реагирующим компонентам.

Поскольку основным преимуществом использования React является его компоновка, теперь нам нужно разбить единственную таблицу стилей less на отдельные фрагменты. Это не так плохо, как кажется, например, если бы у нас был класс с именем blogItem, у которого была куча меньшего, что стилизовало карточку товара, мы создаем стилизованный компонент с именем BlogItem и копируем в него все стили. Вы можете сохранить все вложенные стили и медиа-запросы на месте.

.blogItem {
  font-size: 12px;
  margin-top: 24px;
  //..many more stylings excluded
}

идет к:

export const StyledBlogItem = styled.div`
  font-size: 12px;
  margin-top: 24px;
  //...many more stylings excluded
`

export const BlogItem = props => <StyledBlogItem props={props} />

Шаг 4. Преобразуйте все переменные, на которые есть ссылки в таблицах стилей less

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

import styled from 'styled-components'

export const BlogItem = styled.div`
  ${({ theme }) => `
      color: theme['color'];
    
    `}
`

Единственная проблема здесь в том, что вам нужно следить за любым местом, где переменная с меньшим значением умножается или делится на число. Примеры этого включают умножение размера шрифта, радиуса границы или толщины границы на константу. В этом примере ниже у нас есть переменная less с именем global-border-radius, которую мы определяем как 12px. Можно получить меньший радиус границы, разделив его на число в другом месте таблицы стилей. Здесь класс blogItem будет иметь радиус границы 6 пикселей, хотя глобальное значение равно 12 пикселей.

@global-border-radius: 12px;

.blogItem {
  border-radius: @global-border-radius / 2;
}

Стилизованные компоненты не могут с этим справиться, потому что вы, по сути, пытаетесь разделить строку 12px на число 2. Вот функция, которую вы можете скопировать и использовать, которая сделает это за вас автоматически:

export const modifySize = (fontString, modifyFrac) => {
  const fontNumber = parseFloat(fontString)
  const fontUnit = fontString.replace(/[0-9]/g, '')
  return `${fontNumber * modifyFrac}${fontUnit}`
}

const BlogItem = styled.div`
  ${({theme})=> `
    border-radius: `${modifySize(theme['global-border-radius'], 2)}`
  `}
`

Наша функция modifySize разбивает строку 12px на число 12 и строку px. Он изменит число по коэффициенту, который вы передадите, и вернет строку с правильным размером.

Шаг 5. Преобразуйте примеси в функции

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

heading (@selector, @size, @color: @theme-title) {
  text-align: center;
  font-size: @size;
  font-weight: bold;
  color: @color;
}

Мы можем уловить ту же суть, создав функцию, которая будет возвращать строку со всей этой информацией о стилях, а styled-components с радостью добавит ее туда, куда вы пожелаете:

export const heading = (theme, size, color) => {
  const setColor = color ? color : theme['theme-title']
  //I can set a default color if color isn't passed in

  return `
    text-align: center;
    font-size: ${size};
    font-weight: bold;
    color: ${setColor};
`
}

Самое классное в этом то, что если мы захотим, мы можем даже передавать переменные для управления выводом функции. Единственная загвоздка в том, что если вам нужен доступ к глобальным переменным, вам нужно передать параметр темы в функцию — он не будет автоматически параметром, как при создании стилизованных компонентов. Мы можем вызвать функцию heading следующим образом:

const BlogHeading = styled.div`
  ${({ theme }) => `
    ${heading(theme, '16px', 'black')}
  `}
`

Шаг 6. Используйте && для стилей и стилей с разбросом

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

базовый css:

:not(pre) > code[class*='language-'],
pre[class*='language-'] {
  background-color: #fdf6e3;
}

меньше стайлинга:

:not(pre) > code[class*='language-'] {
  font-family: 'Roboto-Mono';
  padding: 0.1em;
  border-radius: @border-radius-small;
  background-color: @post-highlight;
  color: @post-highlight-text;
}

Решение состоит в том, чтобы добавить && перед стилем, который остался. Каждый & будет увеличивать сгенерированное className для каждого &, который вы добавляете.

const StyledContent = styled.div`
  ${({ theme }) => `
        && :not(pre) > code[class*='language-'] {
            font-family: 'Roboto-Mono';
            padding: 0.1em;
            border-radius: ${theme['border-radius-small']};
            background-color: ${theme['post-highlight']};
            color: ${theme['post-highlight-text']};
            background-color: purple;
        }
    `}
`

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

Первоначально опубликовано наhttps://www.codemochi.com/.