Mobile First - React Styled-Components - CSS Grid
Tags: mobilefirst, react, cssgrid, styledcomponents
Published: 2021-09-02 01:13:49

A la hora de comenzar un proyecto web, ya sea una app o un sitio, si el mismo debe ser responsive, generalmente puede surgir la pregunta; **¿en que resolución comenzar el proyecto?**.

Como su nombre lo indica **mobile first «los móviles primero»**, resume perfectamente esta filosofía de diseño.

Se refiere a un modo de diseñar que tenga en cuenta, en primera instancia, un dispositivo móvil.

A la hora de diseñar, podemos optar por usar frameworks como; Boostrap, Tailwind (el mejor 😁), o hacerlo de forma manual.

En esta guía quiero enseñarte una forma sencilla de encarar el diseño utilizando CSS Grid, Areas y Templates, una vez que definimos la maqueta de nuestro sitio, se puede hacer un diseño responsive de forma muy sencilla.

Queremos lograr una diseño responsive como este:

![Diseño Responsive](https://res.cloudinary.com/dtwdbcfu7/image/upload/v1630541422/posts/01/IMG1_p66x1l.gif)

Para comenzar creamos un proyecto de react y luego instalamos [styled-components.](https://styled-components.com/)

```
npm create-react-app first-mobile
```
```
npm install --save styled-components
```
Ejecutamos nuestro proyecto:
```
npm start
```

Lo primero que vamos hacer es eliminar los archivos que no utilizamos:

* App.css
* App.test.js
* logo.svg
* reportWebVitals.js

**NOTA:** El archivo **index.css** trae unos estilos por defecto para react, estos los utilizaremos con **styled-components** y luego borraremos el archivo.

![repositorio react Limpio](https://res.cloudinary.com/dtwdbcfu7/image/upload/v1630541418/posts/01/IMG2_tmifz7.png)

Editamos los archivos **index.js** y **App.js** para que no nos de errores, deben de quedar así:

App.js
![repositorio react Limpio](https://res.cloudinary.com/dtwdbcfu7/image/upload/v1630541418/posts/01/app.js_k80vkz.png)
index.js
![repositorio react Limpio](https://res.cloudinary.com/dtwdbcfu7/image/upload/v1630541418/posts/01/index.js_ywouez.png)

## Temas que vamos a ver:
[React con Styled-Components](#react-con-styled-components)
[CSS Grid + Grid Area](#css-grid-area)

## React con Styled-Components<a name="react-con-styled-components"></a>

Este módulo nos permite estilizar nuestros componentes, se considera `buenas practicas` definir a que componente le corresponde que estilo.

Lo mejor de **styled-componentes**, es que nos permite escribir nuestro CSS de toda la vida, pero también es posible combinarlo con framworks como Tailwind.

Otra ventaja de styled-componentes; es que nos genera clases automáticas, y es imposible que nuestras clases entren en conflicto entre ellas.

Vamos a comenzar con escribir los estilos globales para toda la app (lo que teníamos en index.css).

Para hacerlo de una forma mas ordenada, crearemos dentro de la carpeta **src**, una carpeta llamada **styles**.

Creamos un archivo llamado **globalStyles.js**, importamos **createGlobalStyle** para crear estilos globales.

Creamos un componente llamado **GlobalStyle**, donde entre bastics (esa comillas simples invertidas) pegamos el cógido de **index.css** (luego podemos borrar el index.css).

```javascript
import {createGlobalStyle} from 'styled-components'

export const GlobalStyle = createGlobalStyle`

//Estilos por defecto que trae React
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}
```

Importamos este componente en el nivel mas alto de la app, en nuestro caso en **App.js**, debe quedar así:
![Global Style React Styled Components](https://res.cloudinary.com/dtwdbcfu7/image/upload/v1630541419/posts/01/IMG3_cztpao.png)

Ahora vamos escribir los componentes para maquetar nuestro sitio y se vea de esta forma:

![React Styled Components](https://res.cloudinary.com/dtwdbcfu7/image/upload/v1630541418/posts/01/IMG4_kejqzw.png)

Pero vamos hacerlo directamente con **styled-components**.
Dentro de la carpeta **styles**, creamos otro archivos llamados **model.js**, (la idea es modelar el sitio).

Importamos styled de styled-componentes, y generamos nuestro primer componente estilizado.

![Primer componente styled-componentes](https://res.cloudinary.com/dtwdbcfu7/image/upload/v1630541418/posts/01/IMG5_rzcnix.png)

Como se puede ver, se crea un componente (Mayúscula), y de **styled** utilizamos un **div**.

**Styled** = contiene todas las etiquetas HTML.

Vamos a proceder a crear el resto de componentes.

```javascript
import styled from 'styled-components'

export const Container = styled.div`
width: 90%;
max-width: 1000px;
margin:20px auto;
`

export const Header = styled.header`
background: blue;
color: #fff;
`

export const Main = styled.main`
padding-left: 2%;
`

export const Sidebar = styled.aside`
background: orange;
min-height: 100px;
`

export const Widget = styled.div`

background: orchid;
height: 100px;
`

export const Footer = styled.footer`
padding: 20px;
background: maroon;
color: #fff;`
```

Ahora vamos a importar nuestros componentes en **App.js** y le vamos asignar una **className** adicional que usaremos en un futuro.

```javascript
import { GlobalStyle } from "./styles/globalStyles";
import { Container, Header, Main, Sidebar, Widget, Footer } from "./styles/model";

function App() {
  return (
    <>
      <GlobalStyle />

      <Container className="contenedor">

        <Header className="header">
          <h1>Header</h1>
        </Header>

        <Main className="contenido">
          <h2>Test</h2>
          <p>Lorem asdasd</p>
        </Main>

        <Sidebar className="sidebar">Sidebar</Sidebar>

        <Widget className="widget-1">Widget-1</Widget>
        <Widget className="widget-2">Widget-2</Widget>

        <Footer className="footer">Footer</Footer>

      </Container>

    </>
  );
}

export default App;
```

Si vemos nuestro proyecto actual, no tiene mucho estilo que digamos, solo sigue el orden jerarquizo de la etiquetas HTML.


![React Styled Components](https://res.cloudinary.com/dtwdbcfu7/image/upload/v1630541419/posts/01/IMG6_kpa5ry.png)

## CSS Grid + Grid Area<a name="css-grid-area"></a>

Para trabajar en Grid, lo que necesitamos es definir una grilla en donde acomodamos nuestro diseño, muchos frameworks usan el sistema de columnas y filas para posicionar objetos en la grilla, nosotros lo haremos de forma manual. 💪

Mi idea no es explicar CSS Grid a fondo 😢 , si no mostrar la magia de **Grid Area**.

En nuestro ejemplo, nuestro diseño cuenta con 3 columnas, y filas automáticas según el contenido.

Vamos a actualizar el código del componente **Container**, y automáticamente ya tendremos grid.

```javascript
export const Container = styled.div`
width: 90%;
max-width: 1000px;
margin:20px auto;
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(4, auto);
`
```
![grid area css](https://res.cloudinary.com/dtwdbcfu7/image/upload/v1630541419/posts/01/IMG7_acjf0q.png)

Ya tenemos una grilla, pero aun no un diseño responsive que se adapte a cualquier resolución.

Es aquí donde aparece **grid area**. Literalmente, nos permite definir con áreas nuestros elementos HTML, a cada componente que creamos, le asignamos un área, debe quedar así:

```javascript
import styled from 'styled-components'

export const Container = styled.div`
width: 90%;
max-width: 1000px;
margin:20px auto;
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(4, auto);
`

export const Header = styled.header`
background: blue;
color: #fff;
grid-area: header; //área

& > h1 {
    margin-left: 2%;
}

`

export const Main = styled.main`
padding-left: 2%;
grid-area: contenido; //área
`

export const Sidebar = styled.aside`
background: orange;
min-height: 100px;
grid-area: sidebar; //área

/*flexbox para acomodar elementos*/

display: flex;
align-items: center;
justify-content: center; //área
`

export const Widget = styled.div`

background: orchid;
height: 100px;
grid-area: ${props => props.className === "widget-1" ? "widget-1" : "widget-2"}; //área

/*flexbox para acomodar elementos*/

display: flex;
align-items: center;
justify-content: center;
`

export const Footer = styled.footer`
padding: 20px;
background: maroon;
color: #fff;
grid-area: footer; //área
`
```

**NOTA**: En el componente Widget por medio de props, podemos asignarle un valor condicional (otra ventaja de styled components).

Una vez que ya tenemos las áreas definidas, tenemos que utilizar **grid-template-area**, para **escribir nuestro diseño**, esto lo hacemos en el archivo **globalStyles.js**

![grid template area](https://res.cloudinary.com/dtwdbcfu7/image/upload/v1630541419/posts/01/IMG8_dmimo1.png)

Como se puede ver, nuestro tamplate, esta basado en 3 columnas (nuestra grilla), solo debemos asignar nuestros componentes al área que deseamos, siempre respetando las 3 columnas para nuestro ejemplo.

Ahora lo que resta es aplicar los diferenntes templates para las diferentes resoluciones, en nuestro caso, como estamos trabajando con la filosofía ***mobile-first***, creamos las áreas de menor a mayor resolución.

Para esto usamos los **media-queries** de toda la vida en **CSS**.
En cada resolución, aplicamos un **grid-template-area**, y redibujamos nuestro diseño.

```javascript
import {createGlobalStyle} from 'styled-components'

export const GlobalStyle = createGlobalStyle`

//Estilos por defecto que trae React
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}


//Estilos para Grid Area

/*Grid Area First Mobile*/

/*min 640px*/
.contenedor {
grid-template-areas: "header header header"
                    "contenido contenido contenido"
                    "sidebar sidebar sidebar"
                    "widget-1 widget-1 widget-1"
                    "widget-2 widget-2 widget-2"
                    "footer footer footer"
;
}


/*min 768px*/
@media screen and (min-width: 768px){
.contenedor{
grid-template-areas:    "header header header"
                        "contenido contenido contenido"
                        "sidebar sidebar sidebar"
                        "widget-1 widget-1 widget-2"
                        "footer footer footer"
;
}    
}

/*min 1024px*/
@media screen and (min-width: 1024px){
.contenedor{
grid-template-areas:    "header header header"
                        "contenido contenido sidebar"
                        "widget-1 widget-2 sidebar"
                        "footer footer footer"
;
}

}

/*min 1280px*/
@media screen and (min-width: 1280px){
.contenedor{
grid-template-areas:    "header header header"
                        "contenido contenido sidebar"
                        "widget-1 widget-1 sidebar"
                        "widget-2 widget-2 sidebar"
                        "footer footer footer"
;
}

}

/*min 1536px*/

`
```

En este caso, solo creamos la estructura de nuestro sitio, pero una vez que rellenamos con nuestro contenido, podemos alinear contenido con flexbox como se muestra en el el ejemplo, en resumen, se puede utilizar el CSS de toda la vida, o combinarlo con otros framworks.

La idea principal es armar una maqueta que sea responsive, luego el contenido de cada área, se debe trabajar por separado, pero si se combina con flexbox, o subgrid, los componentes se puede manipular sin problemas.

**Repo**: [React-StyledComponent-CSS-GridArea](https://github.com/NorbertOSK/React-StyledComponent-CSS-GridArea)

Gracias
Norberto.