Como utilizar CSS com React
Hello =D
Bom, neste post vou falar um pouco sobre como utilizar CSS com React.
Neste exemplo, vou utilizar a lib create-react-app para construir a base inicial do projeto.
Obs.: Todo o projeto você pode conferir no meu github github
Para baixar a logo utilizada neste artigo: logo
Para começar, digite os comandos abaixo:
npx create-react-app using-css-with-reactjs
cd using-css-with-reactjs
npm start
Será criada a seguinte estrutura:
my-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
└── serviceWorker.js
Mantenha a estrutura de arquivos da seguinte maneira:
my-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src
├── App.js
├── index.js
App.js
import React from 'react';
function App() {
return (
<div>
Hello =D
</div>
);
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'))
Agora execute npm run start
para subir a aplicação =D
Certo, uma aba do seu navegador irá abrir com a aplicação sendo executada.
http://localhost:3000/
Tudo certo, agora vamos ao que interessa, CSS in JS \o/
Vou demonstrar como criar uma página de login do Spotify.
Primeiro, vou montar a estrutura HTML do nosso JSX
import React from 'react';
import Logo from './logo.png';
function App() {
return (
<div>
<div>
<img src={Logo} alt="spotify" width="68px" />
<span>Spotify</span>
</div>
<nav>
<ul>
<li><a href="#">SIGN IN</a></li>
<li><a href="#">SIGN UP</a></li>
</ul>
</nav>
<form>
<div>
<input className="input" type="text" name="username" placeholder="Username" required />
</div>
<div>
<input className="input"type="password" name="password" placeholder="Password" required />
</div>
<div>
<input type="checkbox" name="signed" id="signed" /> <label for="signed">stay signed in</label>
</div>
<div>
<button type="submit">SIGN IN</button>
</div>
<div>
<a href="#">Forgot Password?</a>
</div>
</form>
</div>
);
}
export default App;
Ficando desta maneira:
Obs.: Deixei bem simples, para poder criar uma estrutura e aplicar o estilo na página. Deixei inclusive os links sem href, é só um exemplo ;)
Blz, agora, é o momento de darmos vida à página \o/ Yuhuuuuuuuu
Mas como fazer isso!? Já sei, INLINE!!!!!
<div style={{ width:'30px', color: 'red' }}>
Nãaao, jovens gafanhotos!! Nunca faça inline, mantenha sempre um código conciso, de fácil manutenção e previsibilidade. As boas práticas vão continuar, não importa o ano ou as ferramentas que serão utilizadas.
Já imaginaram a "tripa" que viraria!? Sem contar no trabalho que seria giganteeeesco, fora a quantidade de bugs e a total despadronização do código.
E ainda a renderização inline é mais lenta do que utilizar classes.
Tá... blz, e agora, como aplicar o meu maravilhoso CSS com React?
Vamos criar as boas e "velhas" classes! CSS Stylesheet =P
Só que o React utiliza a nomenclatura className
para utilizar uma classe em um componente. Exemplo:
<span className="button-link">Cadê o onclick!?</span>
Então para estilizar a página de login eu vou simplesmente criar um arquivo .css e fazer a chamada no App.js
O src/App.js
ficou assim:
import React from 'react';
import Logo from './logo.png';
import './style.css';
E o style.css
(criei na raíz do src
) ficou assim:
html, body {
height: 100%;
}
body {
margin: 0;
padding: 0;
box-sizing: border-box;
background:#2E3034;
}
Basta criar os arquivos, salvar e ver a página sendo alterada ;D. Tudo o que for escrito no seu arquivo CSS vai funcionar normalmente dentro dos arquivos JS.
Importante, essa abordagem funciona "magicamente" porque utilizei o
create-react-app
para montar toda a estrutura do projeto e por padrão o compilador do código já vem todo configurado, que no caso é owebpack
, que é um module bundler e faz todo o "trabalho sujo" pra gente, não apenas de css, são várias outras coisas (dariam outro artigo hehehe) ;D
Se por acaso você preferir configurá-lo manualmente você vai precisar adicionar o
css-loader
para que os arquivos css sejam chamados dentro dos seus arquivos JS.
Existem outros modules bundlers também, como o Rollup e o Parcel, cada um tem suas características e se adequam melhor a cada cenário.
Blz, agora voltando ao css :P
Adicionei algumas classes no arquivo src/style.css
, ficando desta maneira:
html, body {
height: 100%;
}
body {
margin: 0;
padding: 0;
box-sizing: border-box;
background:#2E3034;
}
a {
color: inherit;
text-decoration: inherit;
}
#root {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.menu {
margin: 24px 0;
}
.menu ul li { display: inline; }
.menu ul {
list-style:none;
}
.menu ul li a {
padding: 2px 10px;
display: inline-block;
color: #fff;
text-decoration: none;
font-weight: 500;
border-bottom: 2px solid transparent;
}
.menu ul li a:hover {
border-bottom: 2px solid #2EBE58;
}
.header {
display: flex;
justify-content: center;
align-items: center;
}
.title {
color: #fff;
line-height: 1.2;
margin: 0;
padding: 0;
font-weight: 900;
max-width: 100%;
width: auto;
display: inline-block;
font-size: 2rem;
padding-left: 6px;
}
.input {
font-size: 14px;
line-height: 1;
border-radius: 500px;
padding: 16px 48px 18px;
transition-property: background-color,border-color,color,box-shadow,filter;
transition-duration: .3s;
border-width: 0;
letter-spacing: 1px;
min-width: 160px;
}
.input:focus {
box-shadow: 0 0 0 0;
border: 0 none;
outline: 0;
}
.button {
font-size: 14px;
line-height: 1;
border-radius: 500px;
padding: 16px 48px 18px;
transition-property: background-color,border-color,color,box-shadow,filter;
transition-duration: .3s;
border-width: 0;
letter-spacing: 1px;
min-width: 256px;
background-color: #2EBE58;
color: #fff;
}
.stay {
color: #fff;
font-size: 0.825rem;
text-align: justify;
display: flex;
align-items: center;
padding-left: 24px;
}
.row {
margin: 16px 0;
}
.forgot {
color: #939599;
text-align: center;
font-size: 0.825rem;
letter-spacing: 0.5px;
margin: 16px 0;
}
Reparem que a criação do CSS continua a mesma, nada mudou.
Agora, basta alterar o App.js, adicionando as classes conforme abaixo:
import React from 'react';
import Logo from './logo.png';
import './style.css';
function App() {
return (
<div>
<div className="header">
<img src={Logo} alt="spotify" width="68px" />
<span className="title">Spotify</span>
</div>
<nav className="menu">
<ul>
<li><a href="#">SIGN IN</a></li>
<li><a href="#">SIGN UP</a></li>
</ul>
</nav>
<form>
<div className="row">
<input className="input" type="text" name="username" placeholder="Username" required />
</div>
<div className="row">
<input className="input"type="password" name="password" placeholder="Password" required />
</div>
<div className="stay">
<input type="checkbox" name="signed" id="signed" /> <label htmlFor="signed">stay signed in</label>
</div>
<div className="row">
<button className="button" type="submit">SIGN IN</button>
</div>
<div className="forgot">
<a href="#">Forgot Password?</a>
</div>
</form>
</div>
);
}
export default App;
Salve os arquivos e veja o resultado na sua página, ficou lindo, não!? =D
O conteúdo está no meu github using-css-with-reactjs
Caso queira utilizar a mesma fonte que usei, basta inserí-la no head do public/index.html
, que fica na raíz do projeto.
<link rel="preload" as="font" crossorigin="" type="font/woff2" href="https://sp-bootstrap.global.ssl.fastly.net/8.2.4/fonts/circular-book.woff2">
<link rel="preload" as="font" crossorigin="" type="font/woff2" href="https://sp-bootstrap.global.ssl.fastly.net/8.2.4/fonts/circular-black.woff2">
<link rel="preload" as="font" crossorigin="" type="font/woff2" href="https://sp-bootstrap.global.ssl.fastly.net/8.2.4/fonts/circular-bold.woff2">
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
<link rel="preload" as="font" crossorigin="" type="font/woff2" href="https://sp-bootstrap.global.ssl.fastly.net/8.2.4/fonts/circular-book.woff2">
<link rel="preload" as="font" crossorigin="" type="font/woff2" href="https://sp-bootstrap.global.ssl.fastly.net/8.2.4/fonts/circular-black.woff2">
<link rel="preload" as="font" crossorigin="" type="font/woff2" href="https://sp-bootstrap.global.ssl.fastly.net/8.2.4/fonts/circular-bold.woff2">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
E depois adicionar o font-family no arquivo src/style.css
html, body {
height: 100%;
font-family: Circular,Helvetica,Arial,sans-serif;
}
CSS via props
É bem simples a utilização de CSS com React, mas essa não é a única maneira. É muito comum classes dependerem de props
ou state
da página.
Exemplo:
render() {
let className = 'menu';
if (this.props.isActive) {
className += ' menu-active';
}
return <span className={className}>Menu</span>
}
Referência: react
No exemplo acima a classe
atribuída muda de acordo com o estado do menu, podendo estar ativo isActive
ou não.
Isso é muito utilizado para fazer alterações nos elementos, lembrando que o React funciona de forma declarativa.
Concatenação de classes
Caso precise adicionar uma classe que é alterada (igual foi feito com o menu-active
) a um elemento que já possui estilo é possível fazer assim:
<span className={`menu ${className}`}>
Utilizei template-string
pra facilitar a "concatenação" dos estilos, bem simples ;D
Pré-processadores de CSS
Bom, SASS e LESS são muito utilizados para ajudar a criar CSS. Auxiliam no reúso de código, manutenção, efeitos e muito mais.
Mas como utilizar SASS com React? "Não" é possível.