Styled Components Basics (Spanish)
Tags: react, beginners, webdev, styledcomponents
Published: 2020-05-25 04:11:46

## Introducción.

Styled Components es una alternativa de mejorar CSS para diseñar componentes en React.

Y es que tiene bastantes ventajas para utilizar esta hermosa librería para diseñar nuestros componentes.

* Sin errores al asignar nombres a nuestras clases CSS, esto gracias a que se generan nombres únicos, evitando sobrescribir alguna clase.

* Eliminación de CSS no utilizable.

* Mejora el mantenimiento, nunca tendrá que buscar en diferentes archivos para encontrar el estilo que afecta a su componente, por lo que el mantenimiento es muy fácil.

* Sigue escribiendo CSS estándar y deje que el componente con estilos se encargue del resto.

* Puede crear estilos de componentes globales sin problemas.

**Estos son algunos beneficios, pero aún hay más.**

## Instalación.

La instalación es muy simple con el comando:

```
npm install --save styled-components
```

## Plugin.

Si tu entorno de trabajo es VSCode, te recomiendo instalar el siguiente plugin:

**vscode-styled-components**

Te ayuda a:
* Resaltado de sintaxis para componentes con estilo en JavaScript y TypeScript.

* CSS IntelliSense detallado mientras trabaja en cadenas con estilo.

* Informe de error de sintaxis.

## Antes de iniciar.

Puedes tener un componente así:

```jsx
const Test = () => (
  <div className="container">
    <h1 className="title">Title</h1>
    <p className="description">Paragraphs</p>
  </div>
}
```

Normalmente cuando trabajas con CSS puedes realizar algo como esto:

```css
.container {
  padding: 10px;
  background-color: #0ac1a8;
  font-family: "Lato", sans-serif;
}

.title {
  margin: 1em 0 0 0;
  letter-spacing: 0.8px;
}

.description {
  font-size: 20px;
  font-weight: 300;
  font-style: italic;
}
```

Y tener tus estilos y componente en archivos diferentes, pero con styled-components estos estilos se mantienen en el mismo archivo.

## Importamos la librería.

Antes de iniciar debes de importar las librerías para iniciar a trabajar.

```jsx
import React from "react";
import styled from "styled-components";
```

## Creando un componente de estilos.

Cuando está definiendo estilos, en realidad está creando componentes de React, el ejemplo anterior puedes transformarlo de esta manera:

```jsx
const Test = () => (
  <Container>
    <Title>Title</Title>
    <Description>Paragraph</Description>
  </Container>
);

const Container = styled.div`
  padding: 10px;
  background-color: #0ac1a8;
  font-family: "Lato", sans-serif;
`;

const Title = styled.h1`
  margin: 1em 0 0 0;
  letter-spacing: 0.8px;
`;

const Description = styled.p`
  font-size: 20px;
  font-weight: 300;
  font-style: italic;
`;
```

Puedes observar que mantiene CSS normal, y cada uno de los componentes se comporta como una etiqueta HTML.

Si abres tú navegador en "inspeccionar elemento", podrás observar una estructura HTML normal y se genera nombres únicos para evitar sobrescribir cada una de las clases de CSS.

> CSS esta definido de manera global en toda su aplicación y cuando está crece puede ser difícil de administrar, aumentando la posibilidad de tener conflictos de nombres de estilos, lo que resuelve styled-components al generar nombres únicos a las clases. 

![styled-component](https://dev-to-uploads.s3.amazonaws.com/i/4basyp2t68bj8eb5eez3.png)

Puedes crear componente con cualquier etiqueta **HTML**, **img**, **p**, **h1**, **div**, **span**, etc.

## Módulos CSS.

Puedes hacer que CSS tome un comportamiento similar a Styled Components utilizando módulos CSS.

El CSS dentro de un módulo está disponible sólo para el componente que lo importó, y no tiene que preocuparse por los conflictos de nombres.

```jsx
import styles from './styles.css'

const Test = () => (
  <div className={styles.container}>
    <p className={styles.paragraph}>Welcome!</p>
    <input
      className={styles.input}
      placeholder="user"
      type="text"
      inputColor="#20534c"
    />
    <input className={styles.input} placeholder="password" type="password" />
    <button className={styles.button} onClick={this.login}>
      Login
    </button>
  </div>
);
```

Pero esto genera un código muy sucio, a comparación de Styled 
Components.

```jsx
const Test = () => (
  <Container>
    <Paragraph>Welcome!</Paragraph>
    <Input placeholder="user" type="text" inputColor="#20534c" />
    <Input placeholder="password" type="password" />
    <Button onClick={this.login}>Login</Button>
  </Container>
);
```

## Usando props (accesorios).

Puedes enviar props a tus componentes de estilo, para crear diferentes comportamientos gracias a las funciones interpoladas.

```jsx
const Test = () => (
  <Container>
    <Button login color="white">
      Login
    </Button>
    <Button bold color="#0ac1a8">
      Register
    </Button>
  </Container>
);

const Container = styled.div`
  width: 100%;
  display: flex;
  justify-content: center;
`;

const Button = styled.button`
  width: 100px;
  margin: 10px;
  font-size: 1em;
  border-radius: 3px;
  padding: 0.25em 1em;
  border: 2px solid #0ac1a8;
  color: ${(props) => props.color};
  font-weight: ${(props) => props.bold && "bold"};
  background-color: ${(props) => (props.login ? "#0ac1a8" : "#ffffff")};
`;
```

Como puedes ver hay varias formas de pasar props a nuestro componente de estilos.

* Obtener el color desde el componente Test.

```js
color: ${(props) => props.color};
```

* Utilizar un operador ternario para intercambiar el color de fondo.

```js
background-color: ${(props) => (props.login ? "#0ac1a8" : "#ffffff")};
```

* También puedes utilizar && (cortocircuito).

```js
font-weight: ${(props) => props.bold && "bold"};
```

* O si deseas varios cambios puedes realizar lo siguiente.

```js
${(props) =>
  props.login &&
  ` color: white; 
  font-weight: normal; 
  background-color: #0ac1a8;`}
```

Y de esta forma reducir tu código a sólo una prop.

![Botones](https://dev-to-uploads.s3.amazonaws.com/i/6y5xjz4592bninmr2s0p.png)

**Importante:** Los componentes de estilos pasan atributo HTML conocido por el DOM, excepto las props ya que son personalizados.

```jsx
const Test = () => (
  <>
    <Input placeholder="name" type="text" inputColor="#20534c" />
    <Input placeholder="lastname" type="text" />
  </>
);

const Input = styled.input`
  margin: 0.5em;
  padding: 0.5em;
  border-radius: 3px;
  border: 1px solid #00bfa5;
  color: ${(props) => props.inputColor || "#1976d2"};
`;
```

Resultado:

![Input1](https://dev-to-uploads.s3.amazonaws.com/i/hcqq62pb3femh53mvc9l.png)

![Input2](https://dev-to-uploads.s3.amazonaws.com/i/8w467g6hkql9nc6htzpu.png)

> Styled Components es suficientemente inteligente para filtrar atributos HTML y enviarlos al DOM como **placeholder** y **type**, pero el prop **inputColor** no pasa al DOM.

## Herencia de estilos.

Puedes crear un nuevo componente que herede de otro y sobrescribir los estilos del mismo tipo.

```jsx
const Test = () => (
  <>
    <Title>Login</Title>
    <SubTitle>Register</SubTitle>
  </>
);

const Title = styled.h1`
  color: #0ac1a8;
  font-family: "Lato", sans-serif;
`;

const SubTitle = styled(Title)`
  color: #303030;
`;
```

De esta forma hereda los estilos y sobrescribe los del mismo tipo.

![Titulo](https://dev-to-uploads.s3.amazonaws.com/i/fveouc8wjws3ybasvmhu.png)

> Podemos heredar componentes propios o de terceros y modificar sus estilos.

## Modificar etiqueta.

En el ejemplo anterior hay dos h1.

```html
<h1 class="sc-fzoXzr dMpzlw">Login</h1>
<h1 class="sc-fzoXzr sc-fzpjYC iywToi">Register</h1>
```

Puedes modificar la etiqueta con **as**, es una prop que permite modificar la etiqueta del componente.

```jsx
const Test = () => (
  <>
    <Title>Login</Title>
    <SubTitle as="h2">Register</SubTitle>
  </>
);
```

El resultado es el siguiente.

```html
<h1 class="sc-fzoXzr dMpzlw">Login</h1>
<h2 class="sc-fzoXzr sc-fzpjYC iywToi">Register</h2>
```

De esta forma puedes heredar estilos y modificar las etiquetas de tus componentes.

## Usando CSS.

Para usar la función auxiliar es necesario importarla.

```jsx
import styled, { css } from "styled-components";
```

Puedes definir estilos CSS de esta manera:

```jsx
const Paragraph = css`
  font-size: 1em;
  letter-spacing: 1.6px;
  ${(props) => (props.font ? "font-weight: 300;" : "font-weight: 400;")};
`;
```

Esto puede ser útil cuando tienes estilos similares que puedes usar en varios componentes:

```jsx
const AboutBio = styled.p`
  ${Paragraph};
  color: #00bfa5;
`;

const AboutAddress = styled.p`
  ${Paragraph};
  color: #1976d2;
`;
```

> Esto no genera otras clases CSS, sólo se incorporan los estilos a las dos clases.

## Modificar estilos de hijos.

Si necesita modificar los estilos de uno de los elementos secundarios, puede agregar selectores.

```jsx
const List = styled.li`
  color: #303030;
  list-style: none;
  font-weight: bold;
  font-family: "Roboto", sans-serif;

  a {
    color: #0ac1a8;
  }
`;
```

La referencia "**a**" se aplicará a los hijos de cualquier profundidad, si sólo desea referirse a los hijos directos debe de usar > **a**.

![List](https://dev-to-uploads.s3.amazonaws.com/i/07x84luyszz027zs2if8.png)

## SCSS.

El preprocesador que utiliza Styled Components, **Stylis**, admite una sintaxis similar a SCSS para los estilos de anidamiento.

```jsx
const Test = () => (
  <>
    <List>Hello world!</List>
    <List>Hello world!</List>
    <List className="something">Hello world!</List>
    <div>Hello world!</div>
    <List>Hello world!</List>
    <div className="something-else">
      <List>Hello world!</List>
    </div>
  </>
);

const List = styled.div`
  color: #303030;
  font-family: "Roboto", sans-serif;

  &:hover {
    font-weight: bold;
  }

  & ~ & {
    background-color: red;
  }

  & + & {
    background-color: greenyellow;
  }

  &.something {
    background-color: orange;
  }

  .something-else & {
    background-color: grey;
  }
`;
```

## Refiriéndose a otros componentes.

En lugar de sólo referirse a cualquier tipo de selectores, también puede referirse a otros componentes de estilos.

```jsx
const Title = styled.h1`
  color: blue;
`;

const Content = styled.div`
  ${Title} {
    color: green;
  }
`;
```

Esto anulará los estilos originales de **Title**.

## Animaciones.

Puedes hacer animaciones importando **keyframes**.

```jsx
import styled, { keyframes } from "styled-components";
```

Y crear una animación como en CSS.

```jsx
const change = keyframes`
  0% { transform: scale(0.7,0.7) }
  100% { transform: scale(1.5,1.5) }
`;

const Text = styled.span`
  font-size: 1.2rem;
  padding: 2rem 1rem;
  display: inline-block;
  animation: ${change} 2s linear infinite;
`;
```

## Estilos globales.

Puedes crear estilos globales importando **createGlobalStyle**.

```jsx
import { createGlobalStyle } from "styled-components";
```

De esta forma tener estilos globales para toda tu aplicación.

```jsx
const StyledGlobal = () => <GlobalStyle />;

const GlobalStyle = createGlobalStyle`
  body {
    margin: 0;
    padding: 0;
    color: #303030;
    background-color: #f6f6f6;
    font-family: 'Lato', sans-serif;
  }
`;

export default StyledGlobal;
```

Importa el componente global en el componente raíz de su aplicación.

```jsx
import StyledGlobal from "../utils/StyledGlobal";
```

Espero les guste :)