Styling Tools

Styling Tools

Tools für externe Stylesheets:

  • Paket classnames
  • CSS-Module
  • SCSS

CSS-in-JS libraries:

  • emotion
  • styled-components
  • linaria
  • ...

classnames

Hilfs-Utility: npm-Paket classnames:

import classNames from 'classnames';

<div
  className={classNames({
    todoitem: true,
    completed: props.completed,
  })}
>
  [...]
</div>;

CSS Module

Bei create-react-app sind CSS-Module vorkonfiguriert; Diese erlauben das Verwenden von CSS-Klassennamen, die garantiert über CSS-Dateien hinweg eindeutig sind.

import styles from './TodoItem.module.css';

<div className={styles.todoItem + ' ' + styles.completed}>
  ...
</div>;

möglicher Output im HTML:

<div
  class="TodoItem_todoItem__L9V1E TodoItem_completed__9bPW1"
>
  ...
</div>

CSS Module und classnames

<div className={classNames({
  [styles.todoitem]: true,
  [styles.completed]: props.completed
})}>

CSS-in-JS

CSS-in-JS: JavaScript wird verwendet, um Stylesheets zu erzeugen und anzufügen

Heutzutage wird es als ok angesehen, Styling-Informationen in der gleichen Datei abzulegen, wie JavaScript / HTML

CSS-in-JS

Libraries:

  • emotion
  • styled-components
  • linaria
  • ...

CSS-in-JS

grundlegendes Beispiel in Emotion:

import { css } from '@emotion/css';

<button
  className={css({
    color: 'blue',
    '@media (min-width: 600px)': { color: 'green' },
    '&:hover': { color: 'red' },
  })}
>
  foo
</button>;

CSS-in-JS

alternative Notation: via "tagged template strings"

<button
  className={css`
    color: blue;
    &:hover {
      color: red;
    }
  `}
>
  foo
</button>

CSS-in-JS

Empfehlung: Verwenden der css-Property statt className (benötigt zusätzliche Source-Code-Transformation):

/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';

<button css={css({ color: 'blue' })}>foo</button>;

Styled components

styled components: Zugang, bei dem Komponenten erstellt werden, deren einzige Aufgabe es ist, Styling auf bestehende HTML-Elemente anzuwenden

Beispiel: PrimaryButoon = ein button-Element mit zusätzlichem Styling

Styled components

Erstellen eines "styled component" mit emotion:

import styled from '@emotion/styled';

const PrimaryButton = styled.button({
  color: 'blue',
  '&:hover': { color: 'red' },
});

Styled components

theoretische manuelle Variante:

function PrimaryButton(props) {
  return (
    <button
      {...props}
      className={css({
        color: 'blue',
        '&:hover': { color: 'red' },
      })}
    />
  );
}

Styled components

dynamische Stile via Props:

mit JavaScript:

const Button = styled.button({
  padding: 8,
  color: (props) => (props.primary ? 'blue' : 'black'),
});

mit TypeScript:

const Button = styled.button<{ primary: boolean }>({
  padding: 8,
  color: (props) => (props.primary ? 'blue' : 'black'),
});

Ãœbung

Übung: Verwende Styling-Tools, um zusätzliches Styling zu einer bestehenden Anwendung hinzuzufügen (z.B. zur Slideshow)

Animationen

Animationen

  • grundlegende Animationen: via CSS Transitions

Animation des Erscheinens / Verschwindens von Elementen:

  • react-transition-group (basiert auf CSS-Klassennamen)

erweiterte Libraries:

  • framer motion
  • react-spring

Animationen

grundlegende Animationen: via CSS Transitions

.TodoItem {
  background-color: salmon;
  transition-property: background-color;
  transition-duration: 0.5s;
}

.TodoItem--Completed {
  background-color: lightgrey;
}

Erscheinen / Verschwinden von Elementen

Phasen für das Erscheinen / Verschwinden von Elementen:

  • unmounted
  • before entering
  • entering
  • displayed
  • before exiting
  • exiting

Erscheinen / Verschwinden von Elementen

react-transition-group: basiert auf CSS-Klassennamen

Erscheinen / Verschwinden von Elementen

Beispiel mit framer motion:

<AnimatePresence>
  {hovered ? (
    <motion.button
      animate={{ opacity: 1 }}
      initial={{ opacity: 0 }}
      exit={{ opacity: 0 }}
      onClick={() => props.onDelete(props.todo.id)}
    >
      delete
    </motion.button>
  ) : null}
</AnimatePresence>

Erscheinen / Verschwinden von Elementen

Beispiel mit framer motion:

<AnimatePresence>
  {todos.map((todo) => (
    <motion.li
      key={todo.id}
      animate={visibleStyle}
      initial={hiddenStyle}
      exit={hiddenStyle}
    >
      {todo.title}
    </motion.li>
  ))}
</AnimatePresence>

Erscheinen / Verschwinden von Elementen

Beispiel mit react-spring:

<Transition
  items={hovered}
  from={{ opacity: 0 }}
  enter={{ opacity: 1 }}
  leave={{ opacity: 0 }}
  reverse={hovered}
>
  {(style, hovered) =>
    hovered ? (
      <animated.button
        style={style}
        onClick={() => props.onDelete(props.todo.id)}
      >
        delete
      </animated.button>
    ) : null
  }
</Transition>