back to top

React: fogli di stile e animazioni

In questo articolo faremo una rapida introduzione alle diverse metodologie che è possibile usare quando si parla di formattare e personalizzare le applicazioni React usando il CSS. Sarà una veloce panoramica, per maggiori dettagli è opportuno consultare la documentazione. Parleremo poi brevemente delle diverse alternative a disposizione quando si vogliono usare delle animazioni in React. Anche in questo caso si consiglia di leggere la documentazione che è piuttosto chiara ed esaustiva.

Breve parentesi sui fogli di stile

Abbiamo visto come creare delle semplici applicazioni in React. Ma come facciamo se vogliamo usare CSS per personalizzare l’aspetto dei singoli componenti e più in generale dell’intera applicazione? Nelle tradizionali applicazioni, siamo abituati a separare la struttura delle pagine nei file HTML, la formattazione nei file CSS e la logica della nostra applicazione all’interno dei file Javascript. Abbiamo visto però, creando i vari componenti React, che la linea di separazione fra il livello di presentazione e logica non è così marcata. In particolare attraverso l’uso di JSX, un componente racchiude al suo interno struttura e logica. Per quanto riguarda l’uso dei fogli di stile, abbiamo innumerevoli soluzioni in React.

Quando abbiamo usato create-react-app, all’interno della directory src erano presenti due file App.css e index.css. In quel caso veniva usato un approccio estremamente semplice. Ovvero scrivere il codice CSS per ciascun componente all’interno di un file.css per poi importarlo in uno con estensione.js in cui era definito il componente che si voleva personalizzare. Dietro le quinte webpack provvedeva a unire i vari fogli di stile e inserirli all’interno della pagina index.html.

Questo approccio è estremamente semplice è può andare bene per piccoli progetti. Un problema che può presentarsi al crescere delle dimensioni di un’applicazione è che il nome di una classe usata in un componente coincida col nome di un’altra classe. Una possibile soluzione è quella di usare una metodologia precisa per il nome delle classi, per esempio BEM, sviluppata da Yandex. Ma anche in questo caso non è assicurato che non ci sia conflitto fra i nomi dei selettori all’interno dei file CSS.

screenshot sito bem

All’interno di un’applicazione, possiamo comunque usare un CSS preprocessor come Sass.

Un’alternativa interessante è usare i css-modules attraverso i quali si possono creare dei file.css in cui i nomi delle classi e delle animazioni hanno solo visibilità locale. Per cui potremo creare all’interno di due file.css due classi con lo stesso nome, applicheremo le classi agli elementi all’interno del nostro componente e CSS modules provvederà poi a generare un’hash unica per ciascuna classe, in modo che non ci siano conflitti fra i nomi. Cerchiamo di chiarire quanto scritto con un’immagine.

css modules schema funzionamento

CRA non supporta i css-modules di default. Volendo usare questa tecnica possiamo però agire in due modi. Una possibile soluzione è eseguire il comando npm run eject nel nostro progetto e effettuare le opportune modifiche nel file di configurazione di webpack per usare i css-modules. Una seconda alternativa è usare il package custom-react-scripts e lanciare CRA con il seguente comando create-react-app my-app –scripts-version custom-react-scripts

Oltre alle tecniche appena descritte, in React è possibile inserire il codice CSS direttamente all’interno dei componenti ovvero scrivere il codice CSS direttamente all’interno dei file Javascript. React supporta questa tecnica (inline-style) di default ma sono state sviluppate diverse librerie che si possono usare se si preferisce questo approccio. Per un elenco completo vi consiglio di dare un’occhiata a questa repository su github.

Semplici transizioni

Vediamo ora come usare le transizioni CSS in React. Come primo esempio realizzeremo un componente all’interno del quale inseriremo un elemento <div> e un <button>. Cliccando sul pulsante invertiremo il valore di opacità dell’elemento <div> da zero a uno e viceversa.

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.onClick = this.onClick.bind(this);
    this.state = {visible: 1}; 
  }
  onClick(e) {
    this.setState({visible: !this.state.visible});
  }
  render() {
    let buttonText = "Nascondi paragrafo";
    let className = "visible";
    if (!this.state.visible) {
      buttonText = "Mostra paragrafo";
      className = "hidden";
    }
    return (
      <div className="App">
        <button onClick={this.onClick}>{buttonText}</button>
        <p className={className}>Clicca sul pulsante 'Nascondi paragrafo' per nascondere questo paragrafo.</p>
      </div>
    );
  }
}

Il codice dell’esempio è abbastanza simile a quello degli esempi visti nei precedenti articoli. All’interno del file App.css abbiamo inserito il seguente codice. Ogni volta che clicchiamo sul pulsante, verrà invertito il valore di opacità del paragrafo. La transizione avverrà in 500ms e inizierà rapidamente per poi rallentare verso la fine (Per chiarimenti potete dare uno sguardo a questi grafici in cui è possibile paragonare le varie funzioni di interpolazione).

p {
  color: #333;
  transition: opacity .5s ease-out;
}

p.visible {
  opacity: 1
}

p.hidden {
  opacity: 0;
}

Potete vedere il risultato nell’immagine sottostante.

esempio transizioni css

Vediamo ora un altro esempio in cui useremo invece le animazioni CSS.

import React, { Component } from 'react';
import './Form.css';

class Form extends Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.onAnimationEnd = this.onAnimationEnd.bind(this);
    this.state = {valid: true, invalidClassName: ''}; 
  }

  handleSubmit(e) {
    e.preventDefault();
    const value = this.input.value;
    if (/^s*$/.test(value)) {
      this.setState({valid: false, invalidClassName: 'invalid'});
    } else {
      this.setState({valid: true, invalidClassName: ''});
    }
  }
  onAnimationEnd(e) {
    this.setState({invalidClassName: ''});
    console.dir(e.target);
  }
  render() {
    return (
      <form 
        onAnimationEnd={this.onAnimationEnd}  
        className={`form ${this.state.invalidClassName}`} 
        onSubmit={this.handleSubmit} >

        <input 
          type="email"
          placeholder="Inserisci la tua mail"
          ref={input => this.input = input} />
        <input type="submit" value="Iscriviti" />
      
      </form>
    );
  }
}

export default Form;

Abbiamo creato un componente Form. Ogni volta che viene premuto il pulsante ‘Iscriviti’, viene verificato che il campo di input non sia vuoto. In caso contrario viene applicata la classe invalid al form e viene avviata una piccola animazione che abbiamo definito all’interno del file Form.css con il nome shake.

/*
*   Ho preso spunto dall'animazione shake 
*   che potete trovare insieme ad altre interessanti 
*   animazioni CSS nella libreria animate.css
*
*   https://daneden.github.io/animate.css/
*/

@keyframes shake {
  0%, 100% {
    transform: translate3d(0,0,0);
  }
  10%, 30%, 50%, 70%, 90% {
    transform: translate3d(-12px, 0, 0);
  }
  20%, 40%, 60%, 80% {
    transform: translate3d(12px, 0, 0);
  }
}

form.invalid {
  animation: shake 1s;
}

Potete di nuovo vedere il risultato nell’immagine sottostante.

esempio animazioni email css

ReactTransitionCSSGroup e ReactTransitionGroup

React mette a disposizione alcuni utili strumenti per realizzare delle animazioni. Il modulo react-addons-css-transition-group fornisce un’API di alto livello (<ReactCSSTransitionGroup>) per realizzare animazioni usando le transizioni e le animazioni CSS per gli elementi che vengono aggiunti o rimossi dal DOM.

Consideriamo l’ottimo esempio presente sulla documentazione ufficiale.

<ReactCSSTransitionGroup
  transitionName="transizione"
  transitionEnterTimeout={500}
  transitionLeaveTimeout={300}>
  {elementi}
</ReactCSSTransitionGroup>

Ogni volta che un elemento viene aggiunto come discendente dell’elemento <ReactCSSTransitionGroup>, riceve una nuova classe transizione-enter (perché abbiamo passato un’attributo transitionName="transizione" a ReactCSSTransitionGroup) e subito dopo la classe transizione-enter-active che dà il via alla transizione (la transizione dura 500ms in questo caso) al termine della quale viene lanciato l’evento transitionend. React provvede infine a rimuovere entrambi le classi dall’elemento.

Quando invece un elemento viene rimosso, riceve prima la classe transizione-leave. Viene quindi aggiunta la classe transizione-leave-active. Al termine della transizione viene nuovamente lanciato un evento transitionend alla fine del quale l’elemento viene rimosso dal DOM.

Per ulteriori informazioni potete consultare la documentazione ufficiale e vedere un esempio funzionante su CodePen.io

È disponibile anche un’API di basso livello che permette di intercettare una serie di metodi invocati quando gli elementi discendenti dell’elemento <ReactTransitionGroup> vengono aggiunti o rimossi dal DOM. È possibile quindi usare diverse librerie come GSAP per effettuare le animazioni tramite Javascript. Potete trovare maggiori dettagli sulla [documentazione ufficiale]. (https://facebook.github.io/react/docs/animation.html#low-level-api-reacttransitiongroup)

React Motion

Concludiamo questo articolo suggerendovi altre due utili risorse ovvero react-animations e React Motion. La prima è una collezione di animazioni da usare con le librerie che possono esseere impiegate per inserire lo stile dei componenti all’interno dei componenti stessi. La seconda è una libreria per realizzare animazioni più avanzate in maniera semplificata. Vi consiglio anche due interessanti articoli in inglese che spiegano come usare React Motion attraverso un interessante esempio: articolo 1, articolo 2.

Pubblicità
Articolo precedente
Articolo successivo