Comparando métodos de estilo no Next.js

Publicados: 2022-03-10
Resumo rápido ↬ Entre outros, o Next.js se autodenominou: The React Framework for Static Websites . Mas, assim como qualquer outra estrutura cujo objetivo é ajudá-lo a construir o que importa abstraindo tarefas comuns e redundantes, muitas vezes você precisa aprender algo novo e opinativo. Com o Next.js, uma das coisas que você precisa saber é como integrar diferentes métodos CSS com sua API, e esse é o foco deste tutorial.

Como você deve estar ciente, existem muitas perspectivas diferentes sobre CSS-in-JS, e todos nós temos uma opinião sobre o tópico de uma forma ou de outra que pode ser bem diferente das opiniões dos autores de frameworks.

Next.js é uma das cadeias de ferramentas recomendadas ao criar um novo aplicativo React. Ferramentas como Next têm um objetivo simples de abstrair tarefas comumente redundantes ao escrever um aplicativo React. Isso ajuda os desenvolvedores a se concentrarem mais em escrever código do que em reinventar a roda. Embora isso geralmente seja uma coisa boa, também pode ser um pouco tedioso para começar. Por um lado, há um obstáculo a ser superado aprendendo sobre as abstrações e, embora haja um bando disso em Next (Routing, Data Fetching…), um muitas vezes esquecido é Styling.

Para atender a um público mais amplo, o Next.js oferece suporte a várias maneiras de estilizar seus componentes. Se você pertence ao grupo Utility first ou CSS-in-JS não é muito da preocupação do Next, sua preocupação é como você injeta sua escolha em sua API.

O objetivo deste artigo é ajudá-lo a entender como configurar o estilo em seu aplicativo Next. Usaremos métodos diferentes para lidar com a comparação. Implementaremos os diferentes tipos de estilo em um aplicativo de livro que configurei. Os métodos de estilo que veremos incluem:

  1. CSS mundial,
  2. SASS/SCSS,
  3. SASS/SCSS em nível de componente,
  4. CSS em nível de componente (módulos CSS),
  5. Componentes estilizados,
  6. Com estilo JSX,
  7. Emoção.

Pré-requisito

Antes de começarmos nosso tour de estilo, existem algumas nuances do Next que você precisa conhecer.

  1. _app.js
    Este é um componente personalizado que reside na pasta de páginas. Next.js usa esse componente para inicializar páginas.
  2. _document.js
    Assim como _app.js , _document.js é um componente personalizado que o Next.js usa para aumentar as tags <html> e <body> de seus aplicativos. Isso é necessário porque as páginas Next.js ignoram a definição da marcação do documento circundante.
  3. _.babelrc
    Quando presente, o Next.js usa esse arquivo como a única fonte de verdade para algumas configurações internas e dá permissão para estendê-lo.

Lembre-se de que, se seu servidor estiver em execução antes de adicionar o arquivo _app.js , será necessário reiniciá-lo.

Mais depois do salto! Continue lendo abaixo ↓

Criando um próximo aplicativo com create-next-app

Criar um próximo aplicativo com create-next-app é tão simples quanto seguir as etapas abaixo:

  • Instale create-next-app globalmente.
 yarn global add create-next-app // Installs create-next-app globally
  • Crie um novo aplicativo Next chamado styling-in-next .
 create-next-app styling-in-next // Creates a new Next app named styling-in-next
  • Altere o diretório para o novo site.
 cd styling-in-next // Switch directory into the new Next app
  • Execute o site.
 yarn dev -p 3000 // Instruct Next to run on port 3000

Consulte a documentação para obter mais informações sobre como criar e executar um aplicativo Next.

O aplicativo agora deve estar sendo executado em https://localhost:3000 .

Uma captura de tela da página de índice inicial padrão do Next.js
Página de índice inicial padrão do Next.js. (Visualização grande)

Repositório de demonstração

À medida que avançamos, estaremos construindo uma estante de livros artificial aplicando diferentes métodos de estilo a cada livro . O resultado final ficará assim:

Uma captura de tela da demo final com estilo Bookshelf
Estante com estilo final. (Visualização grande)

A imagem acima mostra 6 livros; cada livro terá seus próprios componentes, então aplicaremos um tipo de estilo específico para cada livro específico, ou seja, o Livro 1 fará uso de um estilo global enquanto o Livro 2 fará uso de outro. Assim veremos como funciona cada um desses estilos e como podem ser usados. Isso irá ajudá-lo a tomar uma melhor decisão sobre qual opção escolher.

Para simplificar as coisas, montei um repositório GitHub para você acompanhar. Você pode pegar aqui.

Algumas alterações também foram feitas no iniciador padrão gerado por create-next-app . Pastas como emoção , global , módulos , componentes com estilo etc. foram adicionadas à pasta de styles — com seus arquivos de estilo correspondentes — bem como um diretório de components com vários componentes.

Uma captura de tela das alterações iniciais feitas no diretório de componentes e estilos do repositório de demonstração
Alterações nas pastas de estilos e componentes. (Visualização grande)

O arquivo index.js foi modificado para import e render os components necessários e cada um dos componentes tem uma estrutura semelhante à mostrada na imagem abaixo.

Uma captura de tela das alterações iniciais feitas em BookTwo.js, BookOne.js e index.js
Alterações nos componentes individuais e arquivos de índice. (Visualização grande)

Se você clonou e executou o repositório de demonstração, veja como sua página deve ficar:

Uma captura de tela da página de índice padrão do repositório de demonstração
Página de índice padrão do repositório de demonstração. (Visualização grande)

Com tudo isso fora do caminho, vamos ao estilo.

Estilo global

Uma das coisas comuns que você normalmente faria ao iniciar um novo projeto da web é redefinir ou normalizar seu CSS para que haja uma posição inicial uniforme entre os navegadores. Este é um exemplo perfeito de como usar o CSS Global sem se preocupar com o escopo.

  • Atualize styles/global/globals.css com este Reset Mínimo de CSS estendido.
 /* styles/global/globals.css */ html { box-sizing: border-box; font-size: 16px; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; } *, *:before, *:after { box-sizing: inherit; } body, h1, h2, h3, h4, h5, h6, p, ol, ul { margin: 0; padding: 0; font-weight: normal; } h1, h2, h3, h4, h5, h6 { font-weight: bold; } ol, ul { list-style: none; } img { max-width: 100%; height: auto; } a { color: inherit; text-decoration: none; }
  • Importe o CSS reset styles/global/globals.css em pages/_app.js .
 // pages/_app.js import "../styles/global/globals.css"; function MyApp({Component, pageProps}) { return <Component {...pageProps} />; } export default MyApp;

Estilos globais só podem ser importados em pages/_app.js . Isso é diretamente lógico porque esses estilos serão aplicados a todas as pages e components em seu aplicativo - independentemente de onde você os importe - portanto, é melhor ter uma única fonte de verdade [importar] para manter as coisas simples e/ou se algo der certo errado.

Neste ponto, não temos muitas alterações visuais em nossa estante , pois fizemos apenas alterações de normalização . Uma coisa que você pode notar são as mudanças de fonte e espaçamento.

Uma captura de tela da alteração na estante de demonstração após adicionar uma redefinição de CSS
Alterações na página de índice após adicionar uma redefinição de CSS. (Visualização grande)

SASS/SCSS

Next.js também permite estilizar com SASS com a extensão .sass ou .scss . A instalação do Sass é um requisito. Assim como os estilos globais, eles só podem ser importados em pages/_app.js .

  • Instale o pacote Sass.
 yarn add sass
  • Atualize styles/scss/bookshelf.scss .
 // styles/scss/bookshelf.scss .the-bookshelf { width: 100vw; height: 100vh; background-color: #e3e3e3; display: flex; justify-content: center; align-items: center; .bookshelf-wrap { > .bookshelf { box-shadow: inset 0 -20px #7b5019; padding-bottom: 20px; display: flex; align-items: flex-end; } [class*="book"] { font-size: 32px; letter-spacing: -0.045em; display: flex; transition: 0.2s; &:hover { transform: none; } } .book-info { text-transform: uppercase; writing-mode: sideways-rl; display: flex; justify-content: space-around; flex: 1; align-items: center; font-weight: bold; padding: 16px 0; .title { font-weight: inherit; font-size: 20px; } .author { font-weight: inherit; font-size: 15px; } } } }
  • Atualize também styles/sass/bookone.sass e styles/sass/booktwo.sass assim:
 // styles/sass/bookone.sass .book-one color: #f00 width: 78px height: 350px transform: rotate(-4deg) margin-left: 16px margin-right: 23px background-color: black
 // styles/sass/booktwo.sass .book-two color: #781e0b width: 38px height: 448px margin-right: 23px background-color: #ffab44

SASS ( .sass ) é baseado em recuo. Para facilitar a formatação, você pode instalar esta extensão VSCode para suporte a arquivos SASS (formatação, realce de sintaxe…)

  • Importe os três arquivos de estilo — styles/scss/bookshelf.scss , styles/sass/bookone.sass e styles/sass/booktwo.sass — em pages/_app.js .
 // pages/_app.js import "../styles/globals.css"; import "../styles/scss/bookshelf.scss"; import "../styles/sass/bookone.sass"; import "../styles/sass/booktwo.sass"; function MyApp({Component, pageProps}) { return ; } export default MyApp; // pages/_app.js import "../styles/globals.css"; import "../styles/scss/bookshelf.scss"; import "../styles/sass/bookone.sass"; import "../styles/sass/booktwo.sass"; function MyApp({Component, pageProps}) { return ; } export default MyApp;

Nossa estante está começando a tomar forma. Com os estilos aplicados, o primeiro e o segundo livro devem ser estilizados e exibidos conforme pretendido.

Uma captura de tela da alteração na estante de demonstração após estilizar o primeiro e o segundo livro com SASS
BookOne e BookTwo estilizados com SASS. (Visualização grande)

Módulos CSS

Módulos CSS é um CSS de nível de componente, que vem embutido com o Next e pode ser ativado nomeando os arquivos de estilo com a extensão .module.css . Também é possível usar Módulos CSS com SASS/SCSS com a extensão .module.sass ou .module.scss .

Vamos estilizar o components/BookThree.js com ele.

  • Atualize styles/modules/BookThree.module.css .
 /* styles/modules/BookThree.module.css */ .book-three { color: #df66c3; width: 106px; height: 448px; margin-right: 23px; background-color: #153086; transform: rotate(-4deg); }
  • Importe styles/modules/BookThree.module.css em components/BookThree.js e aplique a classe .book-three .
 // components/BookThree.js import BookThreeStyles from "../styles/modules/BookThree.module.css"; export default function BookThree() { return ( <div className={BookThreeStyles["book-three"]}> <div className="book-info"> <p className="title">the revolt of the public</p> <p className="author">Martin Gurri</p> </div> </div> ); }

Acessar nomes de classe em Módulos CSS é semelhante a Acessadores de propriedade em JavaScript — com a notação de ponto ou colchete. Aqui importamos BookThreeStyles e então usamos a notação de colchetes para aplicar o estilo que temos no arquivo styles/modules/BookThree.module.css .

Se o seletor (neste caso, o nome da classe) foi acessado corretamente, o terceiro livro deve ser estilizado agora.

Uma captura de tela da alteração na demo Bookshelf após estilizar o terceiro livro com CSS Modules
BookThree estilizado com módulos CSS. (Visualização grande)

Emoção

Emotion é uma biblioteca CSS-in-JS e, como qualquer outra CSS-in-JS, permite escrever estilos CSS com JavaScript.

Vamos estilizar o components/BookFour.js com ele.

  • Instale os pacotes: @emotion/core , @emotion/styled , emotion , emotion-server .
 yarn add @emotion/core @emotion/styled emotion emotion-server
  • Atualize styles/emotion/StyledBookFour.js .
 // styles/emotion/StyledBookFour.js import styled from "@emotion/styled"; export const StyledBookFour = styled.div` color: white; width: 38px; height: 400px; margin-left: 20px; margin-right: 10px; background-color: #2faad2; transform: rotate(4deg); `;

Depois de importar styled de @emotion/styled , exportamos o componente de estilo StyledBookFour — não deve ser confundido com o outro componente de estilo CSS-in-JS — aprimorado com o método de emoção com styled como em styled.div . Então podemos usar <StyledBookFour/> como na próxima etapa abaixo.

Saiba mais sobre a função estilizada da emoção.

  • Usar <StyledBookFour/> é semelhante a como você usaria qualquer outro componente React. Importe styles/emotion/StyledBookFour.js em components/BookFour.js e aplique o componente StyledBookFour .
 // components/BookFour.js import {StyledBookFour} from "../styles/emotion/StyledBookFour"; export default function BookFour() { return ( <StyledBookFour className="book-four"> <div className="book-info"> <p className="title">the man died</p> <p className="author">wole soyinka</p> </div> </StyledBookFour> ); }

Com uma dose suficiente de emoção , o quarto livro deve ser assim denominado.

Uma captura de tela da mudança na demo Bookshelf após estilizar o quarto livro com Emotion
BookFour estilizado com emoção. (Visualização grande)

JSX com estilo

Como Global CSS e CSS-Modules, Styled-JSX funciona com Next.js sem necessidade de qualquer configuração extra. Se ajudar, Styled-JSX também é a oferta da Vercel de um CSS baseado em componentes, os mesmos criadores do Next.js.

Vamos estilizar o components/BookFive.js com ele.

Para manter as coisas simples, usamos o modo interno do styled-jsx aqui. Ao passar o prop jsx para o componente <style/> , podemos escrever tanto CSS quanto quisermos, como fizemos com .book-five , com o benefício adicional de o estilo ser localizado no componente <BookFive/> .

 // components/BookFive.js export default function BookFive() { return ( <div className="book-five"> <div className="book-info"> <p className="title">there was a country</p> <p className="author">Chinua Achebe</p> </div> <style jsx>{` .book-five { color: #fff; width: 106px; height: 448px; margin-right: 23px; background-color: #000; transform: rotate(4deg); } `}</style> </div> ); }

E assim, o quinto livro toma seu estilo.

Uma captura de tela da mudança na demo Bookshelf após estilizar o quinto livro com Styled JSX
BookFive estilizado com Styled JSX. (Visualização grande)

Componentes estilizados

Styled-Component, assim como Emotion, também é uma biblioteca CSS-in-JS que permite escrever estilos CSS com JavaScript. A configuração é um pouco complicada.

  • Primeiro, instale babel-plugin-styled-components e styled-components .
 yarn add babel-plugin-styled-components styled-components
  • Crie um arquivo .babelrc na raiz do seu aplicativo e um arquivo pages/_document.js , conforme mostrado na imagem antes (esquerda) e depois (direita) abaixo.
Uma captura de tela da alteração na estante de demonstração após adicionar dois novos arquivos - <code>_.document.js</code> e <code>.babelrc</code>
Novos arquivos adicionados: _document.js e .babelrc . (Visualização grande)
  • Atualize o arquivo .babelrc para incluir a predefinição next/babel e incluir o plug-in styled-components , com a renderização do lado do servidor (ssr) ativada.
 // .babelrc { "presets": ["next/babel"], "plugins": [ [ "styled-components", { "ssr": true } ] ] }
  • Atualize pages/_document.js injetando os estilos renderizados do lado do servidor no <head> .

Lembre-se de que o snippet abaixo ( pages/_document.js ) é uma lógica necessária para que os styled-components funcionem com o Next.js. Você quase não precisa fazer nada além de copiar a lógica conforme indicado na documentação dos componentes com estilo.

 // pages/_document.js import Document from "next/document"; import {ServerStyleSheet} from "styled-components"; export default class MyDocument extends Document { static async getInitialProps(ctx) { const sheet = new ServerStyleSheet(); const originalRenderPage = ctx.renderPage; try { ctx.renderPage = () => originalRenderPage({ enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />), }); const initialProps = await Document.getInitialProps(ctx); return { ...initialProps, styles: ( <> {initialProps.styles} {sheet.getStyleElement()} </> ), }; } finally { sheet.seal(); } } }

Após as atualizações para .babelrc e pages/_document.js , agora podemos começar a usar styled-components.

  • Atualize styles/styled-components/StyledBookSix.js .

styled é um método utilitário interno que transforma o estilo do JavaScript em CSS real. <StyledBookSix/> é, e, pode ser usado como qualquer outro componente React.

 // styles/StyledBookSix.js import styled from "styled-components"; const StyledBookSix = styled.div` color: #fff; width: 106px; height: 448px; margin-right: 23px; background-color: rebeccapurple; `; export default StyledBookSix;

Saiba mais sobre Como usar componentes com estilo no React.

  • Importe styles/styled-components/StyledBookSix.js em components/BookSix.js , usando os styled-components importados <StyledBookSix/> .
 // components/BookSix.js import StyledBookSix from "../styles/styled-components/StyledBookSix"; export default function BookSix() { return ( <StyledBookSix className="book-six"> <div className="book-info"> <p className="title">purple hibiscus</p> <p className="author">chimamanda ngozi adichie</p> </div> </StyledBookSix> ); }

Com a primeira a sexta etapa concluída, a sexta deve ser estilizada e a estante pronta:

Uma captura de tela da alteração na estante de livros de demonstração após estilizar o sexto livro com componentes estilizados
BookSix estilizado com componentes estilizados. (Visualização grande)

É isso.

Se tudo correu bem, então você deve ter a estante completa com os livros esperando para serem lidos.

  • Você pode pegar o código completo no GitHub →

Conclusão

Em meu próprio uso com Next.js, estilos globais e componentes com estilo têm sido suficientes. Mas não há dúvida de que todos esses métodos têm seus prós e contras. E ao decidir qual método usar, lembre-se: no final, é tudo CSS. Neste ponto, acredito que você possa descobrir qual padrão melhor atende a você em seu próximo projeto.

Recursos

Acho que para aprender a configurar métodos de estilo com Next.js, não há lugar melhor do que sua documentação oficial.

Mas também existem repositórios específicos para vários métodos de estilo. Você pode percorrer os vários repositórios para saber mais ou verificar se há atualizações, pois as coisas podem mudar de modo anônimo.

  1. CSS Tailwind
  2. Módulos CSS
  3. Menos
  4. Caneta
  5. Tailwind CSS com emoção
  6. Styletron
  7. Glamour
  8. CXS
  9. Afrodite
  10. Fela
  11. Styled-JSX