# Styling

Er zijn veel manieren om stylesheets toe te passen op React applicaties. We gaan hier twee veel gebruikte manieren bekijken:

* **CSS-in-CSS** (CSS Modules)
* **CSS-in-JS**&#x20;

Elk heeft zijn eigen voor en nadelen. Het is belangrijk om te weten dat geen van deze manieren beter is dan de andere.&#x20;

### CSS Modules

CSS Modules is de aanpak die het hardste aanleunt bij traditionele css bestanden zoals deze gebruikt worden in andere html pagina's. Alle elementen krijgen een `class` toegewezen en krijgen een style toegewezen via een CSS bestand. In React gebruiken we niet `class` maar `className`.

In React willen we alle componenten zo zelfstandig mogelijk kunnen werken zonder te veel afhankelijkheden van elkaar. Daarom proberen we zoveel mogelijk per component een aparte CSS bestand aan te maken. Het is perfect mogelijk om alles in de algemene `index.css` te plaatsen, maar dat gaan we zoveel mogelijk vermijden.&#x20;

We kunnen CSS bestanden toevoegen aan een react component aan de hand van de import mechanisme van javascript.&#x20;

```typescript
import './App.css';
```

Dit CSS bestand kan dan de volgende inhoud hebben:

```css
.container {
    padding: 10px
}
```

We kunnen dan bijvoorbeeld onze `<div>` tags stylen als volgt

```typescript
<div className="container">
      <Header/>
      <List games={games} />
      <InputView onAdd={handleAdd} />
</div>
```

Het nadeel van deze manier is dat we moeten opletten dat al deze CSS bestanden niet dezelfde class names gebruiken. Als dit wel gebeurt dan zullen deze CSS classes met elkaar botsen en zal de ene de andere overschrijven. &#x20;

Om dit probleem op te lossen biedt React een betere manier aan van importeren van CSS bestanden. We gaan gebruik maken van CSS modules. Het gebruik is zeer gelijkaardig aan gewone CSS bestanden maar deze gaan volledig onafhankelijk van elkaar werken. Alle classes krijgen automatisch een willekeurig stuk tekst toegewezen zodat de namen van de classes allemaal uniek zijn. Om gebruik te maken van de CSS Modules moet het CSS bestand de naam krijgen van de Component gevolgd door `.module.css`&#x20;

Als we nu gebruik willen maken van CSS modules in ons `App` component moeten we dit hernoemen naar `App.module.css` en moeten we de manier van importeren iets aanpassen

```typescript
import styles from './App.module.css';
```

We gebruiken hier dan ook niet meer een string als we de className meegeven maar geven hier direct een variabele uit het styles object.

```typescript
  <div className={styles.container}>
    <Header />
    <List games={games} />
    <InputView onAdd={handleAdd} />
  </div>
```

Je kan eventueel de vscode plugin installeren die autocomplete geeft voor de CSS modules.&#x20;

{% embed url="<https://marketplace.visualstudio.com/items?itemName=clinyong.vscode-css-modules>" %}

We kunnen nu de rest van onze componenten beginnen stylen met CSS Modules.

```typescript
// Header.tsx
import styles from "./Header.module.css"

const Header = () => {
  return (
    <h1 className={styles.header}>Welcome to the H2O Game shop</h1>
  );
}

export default Header;
```

```css
/* Header.module.css */
.header { 
  font-size: 22pt;
  border-bottom: 2px solid black;
  text-transform: uppercase;
}
```

Dit gaat onze header een grotere font size geven en in uppercase letters zetten. Er zal ook een lijn onder de titel gezet worden.

```typescript
// Inputview.tsx
...
import styles from "./InputView.module.css";
...

const InputView = ({onAdd} : InputViewProps) => {
  ...
  return (
    <div className={styles.inputView}>
      ...
    </div>
  )
}

export default InputView;
```

```css
/* Inputview.module.css */
.inputView {
  margin: 10px;
  display: flex;
  flex-direction: column;
}

input {
  width: 500px;
  margin: 5px;
  box-sizing: border-box;
}
```

Dit maakt van de div een [flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) layout met als direction 'column'. Dit zorgt ervoor dat de elementen die in de div geplaatst worden verticaal zullen worden geplaatst worden in plaats van horizontaal. De breedte van de input-velden worden allemaal vastgezet op 500 pixels en krijgen allemaal een zwarte rand.

```typescript
// List.tsx
...
import styles from './List.module.css'
...

const List = ({ games }: ListProps) => {
  return (
    <div className={styles.gamesList}>{games.map((game: Game) => {
      return <ListItem game={game}/>
    })}
    </div>
  );
}

export default List;
```

```typescript
// ListItem.tsx
...
import styles from './List.module.css'
...

const ListItem = ({ game }: ListItemProps) => {
  return (
    <div key={game.id} className={styles.gameCard}>
      <div>{game.name}</div>
      <div>{game.releaseYear}</div>
      <div>{game.sales}</div>
    </div>
  )
}

export default ListItem;
```

```css
/* List.module.css */
.gamesList {
  display: flex;
  flex: row;
  flex-wrap: wrap;
}

.gameCard {
  border: 1px;
  padding: 10px;
  width: 200px;
  box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
  transition: 0.3s;
  background-color: white;
  border-radius: 5px; /* 5px rounded corners */
  margin: 10px
}
```

We zorgen met de `gamesList` class dat de div elementen van de games worden in een rij gepositioneerd. Met de `flex-wrap` property zorgen we dat de elementen op een nieuwe lijn worden geplaatst als deze niet op 1 lijn passen. We willen alle games laten zien aan de gebruiker als kaartjes met een schaduw en nog verschillende eigenschappen.

Je layout zal er ongeveer als volgt uitzien:

![](https://846376556-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-McTNvdIuKynd-zW5FrJ%2F-Mf4mJvASyNk0_6Q2DDI%2F-Mf4mUsqSKzewv2BqE4y%2Fimage.png?alt=media\&token=d2688996-6417-442c-bf86-41ab98ee477a)

### CSS-in-JS

De manier van styling die we hierboven hebben toegepast is zeer gelijkaardig met hoe je in andere HTML paginas gebruik hebt gemaakt van CSS styles. Je hebt een apart CSS-bestand waarin je alle stijlen beschrijft aan de hand van classes en gebruikt classNames voor deze te gebruiken. In react heb je een alternatieve manier om dit te doen, je kan de styles rechtstreeks ook in javascript definiëren. Het voordeel van deze manier is dat we niet afhankelijk zijn van aparte CSS-bestanden en alles wat nodig is om een component te renderen in javascript beschikbaar is.

De eerste manier om dit te doen is via **inline styles**. Je geeft rechtstreeks de styles mee aan de hand van de `style` property.&#x20;

```typescript
const Header = () => {
  return (
    <h1 style={{fontSize: '22pt', borderBottom: '2px solid black', textTransform: 'uppercase'}}>Welcome to the H2O Game shop</h1>
  );
}
```

Je ziet dat we hier ook niet gebruik maken van de  `font-size`, `border-bottom` en `text-transform` die we in het gewone CSS-bestand gebruikte. De regel is dat we hier de camelCase varianten gebruiken van onze CSS properties. Zo wordt bv`font-size` dus `fontSize`.

In plaats van het object rechtstreeks mee te geven aan de property kan je deze ook in een aparte constante plaatsen.

```typescript
import { CSSProperties } from 'react';

const headerStyle : CSSProperties = {
  fontSize: '22pt', borderBottom: '2px solid black', textTransform: 'uppercase'
}

const Header = () => {
  return (
    <h1 style={headerStyle}>Welcome to the H2O Game shop</h1>
  );
}

export default Header;
```

Niet alle dingen die je kan gebruiken in CSS kan je in CSS-in-JS gebruiken. Dingen zoals animaties zijn hierdoor niet eenvoudig te implementeren. Daarom wordt er vaak voor CSS-in-JS gebruik gemaakt van de library `styled-components`&#x20;

Je kan deze eenvoudigweg installeren door

```
npm install styled-components
npm install @types/styled-components
```

uit te voeren in je terminal en dan te importeren op de volgende manier

```typescript
import styled from 'styled-components'
```

zo kunnen we onze header component ook als volgt stylen

```typescript
import styled from 'styled-components'

const TitleHeader = styled.div`
  font-size: 22pt;
  border-bottom: 2px solid black;
  text-transform: uppercase;
`;

const Header = () => {
  return (
    <TitleHeader>Welcome to the H2O Game shop</TitleHeader>
  );
}

export default Header;
```

Je merkt op dat we hier wel de standaard CSS properties kunnen gebruiken als in een gewoon CSS-bestand.&#x20;

We gaven al aan dat we zelfs animaties kunnen definiëren in CSS. Dit kunnen we op de volgende manier doen:

```typescript
import styled, { keyframes } from 'styled-components'

const fadeIn = keyframes`
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
`;

const TitleHeader = styled.div`
  font-size: 22pt;
  border-bottom: 2px solid black;
  text-transform: uppercase;
  animation: 1s ${fadeIn} ease-out;
`;

const Header = () => {
  return (
    <TitleHeader>Welcome to the H2O Game shop</TitleHeader>
  );
}

export default Header;
```

### UI Frameworks

Er zijn een tal van frameworks die het gebruik van zelf CSS schrijven minimaliseren. Je maakt daar gebruik van herbruikbare componenten die allemaal al voor jou geschreven zijn. De meest bekende zijn:

* <https://material-ui.com/>
* <https://react-bootstrap.github.io/>
* <https://tailwindcss.com/>

Deze vereenvoudigen het ontwikkelproces drastisch en zorgen ervoor dat er een bepaald design systeem wordt gebruikt. Dit zorgt ervoor dat het ontwikkelen van web applicaties drastisch kan versneld worden.&#x20;
