Flutter para Desarrolladores Web (HTML/CSS)

Contents:

Esta página es para usuarios familiarizados con la sintaxis HTML y CSS para la organización de componentes de UI de una aplicación. Esta contrasta ejemplos de código en HTML/CSS con su código equivalente en Flutter/Dart.

Este ejemplo asume:

  • El documento HTML inicia con <!DOCTYPE html>, y el modelo de caja CSS se establece para todos los elementos HTML en border-box, para obtener consistencia con el modelo de Flutter.

    {
      box-sizing: border-box;
    }
    
  • En Flutter, el estilo predeterminado del texto “Lorem ipsum” se define mediante la variable bold24Roboto de la siguiente manera, para mantener la sintaxis simple:

    TextStyle bold24Roboto = TextStyle(
      color: Colors.white,
      fontSize: 24.0,
      fontWeight: FontWeight.w900,
    );
    

Realizando operaciones básicas de diseño

Los siguientes ejemplos muestran cómo realizar las tareas más comunes de diseño de IU.

Estilos y alineación de texto

El estilo de fuente, tamaño y otros atributos del texto que CSS controla con la propiedad font y color son propiedades individuales de un TextStyle elemento secundario de un widget Text

Tanto en HTML como en Flutter, los elementos secundarios o widgets están anclados en la parte superior izquierda, por defecto.

<div class="greybox">
    Lorem ipsum
</div>

.greybox {
      background-color: #e0e0e0; /* grey 300 */
      width: 320px;
      height: 240px;
      font: 900 24px Georgia;
    }
var container = Container( // grey box
  child: Text(
    "Lorem ipsum",
    style: TextStyle(
      fontSize: 24.0
      fontWeight: FontWeight.w900,
      fontFamily: "Georgia",
    ),
  ),
  width: 320.0,
  height: 240.0,
  color: Colors.grey[300],
);

Ajuste del color de fondo

En Flutter, se establece el color de fondo utilizando la propiedad decoration de un Container’.

Los ejemplos CSS utilizan los colores equivalentes en hexadecimal de la Material color palette.

<div class="greybox">
  Lorem ipsum
</div>

.greybox {
      background-color: #e0e0e0;  /* grey 300 */
      width: 320px;
      height: 240px;
      font: 900 24px Roboto;
    }
var container = Container( // grey box
    child: Text(
      "Lorem ipsum",
      style: bold24Roboto,
    ),
    width: 320.0,
    height: 240.0,
    color: Colors.grey[300],
  );

Centrar componentes

Un widget Center centra a su elemento interno tanto horizontal como verticalmente.

Para lograr un efecto similar en CSS, el elemento primario utiliza un comportamiento de visualización table-cell o flex. Los ejemplos de esta página muestran el comportamiento de Flex.

<div class="greybox">
  Lorem ipsum
</div>

.greybox {
  background-color: #e0e0e0; /* grey 300 */
  width: 320px;
  height: 240px;
  font: 900 24px Roboto;
  display: flex;
  align-items: center;
  justify-content: center; 
}
var container = Container( // grey box
  child:  Center(
    child:  Text(
      "Lorem ipsum",
      style: bold24Roboto,
    ),
  ),
  width: 320.0,
  height: 240.0,
  color: Colors.grey[300],
);

Configuración del ancho del contendor

Para especificar el ancho de un widget Container, utiliza su propiedad width. Este es un ancho fijo, a diferencia de la propiedad CSS Max-width que ajusta el ancho del contenedor hasta un valor máximo. Para imitar ese efecto Flutter, usa las propiedades constraints del Container.

Crea un nuevo widget BoxConstraints con un minWidth o maxWidth.

En el caso de los contenedores anidados, si el ancho de los padres es menor que el ancho del hijo, el Contenedor hijo se dimensiona a sí mismo para que coincida con el padre.

<div class="greybox">
  <div class="redbox">
    Lorem ipsum
  </div>
</div>

.greybox {
  background-color: #e0e0e0; /* grey 300 */
  width: 320px; 
  height: 240px;
  font: 900 24px Roboto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.redbox {
  background-color: #ef5350; /* red 400 */
  padding: 16px;
  color: #ffffff;
    width: 100%;
  max-width: 240px; 
}
var container = Container( // grey box
  child: Center(
    child: Container( // red box
      child: Text(
        "Lorem ipsum",
        style: bold24Roboto,
      ),
      decoration: BoxDecoration(
        color: Colors.red[400],
      ),
      padding: EdgeInsets.all(16.0),
      width: 240.0, //max-width is 240.0
    ),
  ),
  width: 320.0, 
  height: 240.0,
  color: Colors.grey[300],
);

Manipulando posición y tamaño

En los ejemplos siguientes se muestra cómo realizar operaciones más complejas en la posición, el tamaño y el fondo del widget.

Configuración de posición absoluta

De forma predeterminada, los widgets son posicionados de forma relativa a su padre.

Para especificar una posición absoluta para un widget como coordenadas x-y, anídelo en un widget Positioned que, a su vez, está anidado en un widget Stack.

<div class="greybox">
  <div class="redbox">
    Lorem ipsum
  </div>
</div>

.greybox {
  background-color: #e0e0e0; /* grey 300 */
  width: 320px;
  height: 240px;
  font: 900 24px Roboto;
  position: relative; 
}
.redbox {
  background-color: #ef5350; /* red 400 */
  padding: 16px;
  color: #ffffff;
  position: absolute;
  top: 24px;
  left: 24px; 
}
var container = Container( // grey box
  child: Stack(
    children: [
      Positioned( // red box
        child:  Container(
          child: Text(
            "Lorem ipsum",
            style: bold24Roboto,
          ),
          decoration: BoxDecoration(
            color: Colors.red[400],
          ),
          padding: EdgeInsets.all(16.0),
        ),
        left: 24.0,
        top: 24.0,
      ),
    ],
  ), 
  width: 320.0,
  height: 240.0,
  color: Colors.grey[300],
);

Girando componentes

Para rotar un widget, anídalo en un widget Transform. Utiliza las propiedades alignment y origin del widget de transformación para especificar el origen de la transformación (Fulcrum) en términos relativos y absolutos, respectivamente.

Para una rotación 2D simple, el widget se gira en el eje Z utilizando radianes. (grados × π/180)

<div class="greybox">
  <div class="redbox">
    Lorem ipsum
  </div>
</div>

.greybox {
  background-color: #e0e0e0; /* grey 300 */
  width: 320px;
  height: 240px;
  font: 900 24px Roboto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.redbox {
  background-color: #ef5350; /* red 400 */
  padding: 16px;
  color: #ffffff;
  transform: rotate(15deg); 
}
var container = Container( // gray box
  child: Center(
    child:  Transform(
      child:  Container( // red box
        child: Text(
          "Lorem ipsum",
          style: bold24Roboto,
          textAlign: TextAlign.center,
        ),
        decoration: BoxDecoration(
          color: Colors.red[400],
        ),
        padding: EdgeInsets.all(16.0),
      ),
      alignment: Alignment.center,
      transform: Matrix4.identity()
        ..rotateZ(15 * 3.1415927 / 180),
    ), 
  ),
  width: 320.0,
  height: 240.0,
  color: Colors.grey[300],
);

Escalando componentes

Para escalar un widget arriba o abajo, anidarlo en un widget Transform. Use las propiedades alignment y origin del widget Transform para especificar el origen (fulcrum) de la transformación en términos relativos o absolutos respectivamente.

Para una operacion de escalamiento simple a lo largo del eje x crea un nuevo objeto de identidad Matrix4 y utilice su método scale() para especificar el factor de escala.

Cuando se escala un widget primario, los widgets secundarios se escalan en consecuencia.

<div class="greybox">
  <div class="redbox">
    Lorem ipsum
  </div>
</div>

.greybox {
  background-color: #e0e0e0; /* grey 300 */
  width: 320px;
  height: 240px;
  font: 900 24px Roboto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.redbox {
  background-color: #ef5350; /* red 400 */
  padding: 16px;
  color: #ffffff;
  transform: scale(1.5); 
}
var container = Container( // gray box
  child: Center(
    child:  Transform(
      child:  Container( // red box
        child: Text(
          "Lorem ipsum",
          style: bold24Roboto,
          textAlign: TextAlign.center,
        ),
        decoration: BoxDecoration(
          color: Colors.red[400],
        ),
        padding: EdgeInsets.all(16.0),
      ),
      alignment: Alignment.center,
      transform: Matrix4.identity()
        ..scale(1.5),
     ), 
  width: 320.0,
  height: 240.0,
  color: Colors.grey[300],
);

Aplicando linear gradient

Para aplicar linear gradient a un background de un widget, anidarlo en un widget Container Entonces use la propiedad decoration del widget Container crea un objeto BoxDecoration, y usa la propiedad gradient de BoxDecoration para transformar el relleno del background.

El “ángulo” del gradient se basa en los valores de alineación (x, y):

  • Si los valores de “x” iniciales y finales son iguales, el gradiente es vertical (0° 180°).
  • Si los valores de “y” iniciales y finales son iguales, el gradiente es horizontal (90° 270°).

Vertical gradient

<div class="greybox">
  <div class="redbox">
    Lorem ipsum
  </div>
</div>

.greybox {
  background-color: #e0e0e0; /* grey 300 */
  width: 320px;
  height: 240px;
  font: 900 24px Roboto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.redbox {
  padding: 16px;
  color: #ffffff;
  background: linear-gradient(180deg, #ef5350, rgba(0, 0, 0, 0) 80%); 
}
var container = Container( // grey box
  child: Center(
    child: Container( // red box
      child: Text(
        "Lorem ipsum",
        style: bold24Roboto,
      ),
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: const Alignment(0.0, -1.0),
          end: const Alignment(0.0, 0.6),
          colors: <Color>[
            const Color(0xffef5350),
            const Color(0x00ef5350)
          ],
        ),
      ), 
      padding: EdgeInsets.all(16.0),
    ),
  ),
  width: 320.0,
  height: 240.0,
  color: Colors.grey[300],
);

Horizontal gradient

<div class="greybox">
  <div class="redbox">
    Lorem ipsum
  </div>
</div>

.greybox {
  background-color: #e0e0e0; /* grey 300 */
  width: 320px;
  height: 240px;
  font: 900 24px Roboto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.redbox {
  padding: 16px;
  color: #ffffff;
  background: linear-gradient(90deg, #ef5350, rgba(0, 0, 0, 0) 80%); 
}
var container = Container( // grey box
  child: Center(
    child: Container( // red box
      child: Text(
        "Lorem ipsum",
        style: bold24Roboto,
      ),
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: const Alignment(-1.0, 0.0),
          end: const Alignment(0.6, 0.0),
          colors: <Color>[
            const Color(0xffef5350),
            const Color(0x00ef5350)
          ],
        ),
      ), 
      padding: EdgeInsets.all(16.0),
    ),
  ),
  width: 320.0,
  height: 240.0,
  color: Colors.grey[300],
);

Manipulando Shapes

Los siguientes ejemplos muestran cómo crear y personalizar formas.

Redondeo de esquinas

Para redondear esquinas de un shape, use la propiedad borderRadius de un objeto BoxDecoration. Crea un objeto BorderRadius que especifica los radios para redondear cada esquina.

<div class="greybox">
  <div class="redbox">
    Lorem ipsum
  </div>
</div>

.greybox {
  background-color: #e0e0e0; /* gray 300 */
  width: 320px;
  height: 240px;
  font: 900 24px Roboto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.redbox {
  background-color: #ef5350; /* red 400 */
  padding: 16px;
  color: #ffffff;
  border-radius: 8px; 
}
var container = Container( // grey box
  child: Center(
    child: Container( // red circle
      child: Text(
        "Lorem ipsum",
        style: bold24Roboto,
      ),
      decoration: BoxDecoration(
        color: Colors.red[400],
        borderRadius: BorderRadius.all(
          const Radius.circular(8.0),
        ), 
      ),
      padding: EdgeInsets.all(16.0),
    ),
  ),
  width: 320.0,
  height: 240.0,
  color: Colors.grey[300],
);

Agregando sombras a las cajas

En CSS puedes especificar el desplazamiento de las sombras y la difuminación de forma abreviada usando la propiedad box-shadow. Este ejemplo muestra dos sombras de caja, con las propiedades:

  • xOffset: 0px, yOffset: 2px, blur: 4px, color: black @80% alpha
  • xOffset: 0px, yOffset: 06x, blur: 20px, color: black @50% alpha

En Flutter, cada propiedad y valor es especificado separadamente. Use la propiedad boxShadow de BoxDecoration para crear una lista de BoxShadow widgets. Puedes definir uno o múltiples widgets BoxShadow, puedes aplicarlos para customizar la profundidad de las sombras, el color, etc.

<div class="greybox">
  <div class="redbox">
    Lorem ipsum
  </div>
</div>

.greybox {
  background-color: #e0e0e0; /* grey 300 */
  width: 320px;
  height: 240px;
  font: 900 24px Roboto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.redbox {
  background-color: #ef5350; /* red 400 */
  padding: 16px;
  color: #ffffff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.8),
              0 6px 20px rgba(0, 0, 0, 0.5);
}
var container = Container( // grey box
  child: Center(
    child: Container( // red box
      child: Text(
        "Lorem ipsum",
        style: bold24Roboto,
      ),
      decoration: BoxDecoration(
        color: Colors.red[400],
        boxShadow: <BoxShadow>[
          BoxShadow (
            color: const Color(0xcc000000),
            offset: Offset(0.0, 2.0),
            blurRadius: 4.0,
          ),
          BoxShadow (
            color: const Color(0x80000000),
            offset: Offset(0.0, 6.0),
            blurRadius: 20.0,
          ),
        ], 
      ),
      padding: EdgeInsets.all(16.0),
    ),
  ),
  width: 320.0,
  height: 240.0,
  decoration: BoxDecoration(
    color: Colors.grey[300],
  ),
  margin: EdgeInsets.only(bottom: 16.0),
);

Haciendo círculos y elipses

Hacer círculos en CSS requiere aplicar una solución alternativa aplicando un border-radius de 50% para todos los lados de un rectángulo, aunque hay formas básicas.

Si bien este enfoque es compatible con la propiedad borderRadius de BoxDecoration, Flutter provee una propiedad shape con BoxShape enum para este propósito.

<div class="greybox">
  <div class="redcircle">
    Lorem ipsum
  </div>
</div>

.greybox {
  background-color: #e0e0e0; /* gray 300 */
  width: 320px;
  height: 240px;
  font: 900 24px Roboto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.redcircle {
  background-color: #ef5350; /* red 400 */
  padding: 16px;
  color: #ffffff;
  text-align: center;
  width: 160px;
  height: 160px;
  border-radius: 50%; 
}
var container = Container( // grey box
  child: Center(
    child: Container( // red circle
      child: Text(
        "Lorem ipsum",
        style: bold24Roboto,
        textAlign: TextAlign.center, 
      ),
      decoration: BoxDecoration(
        color: Colors.red[400],
        shape: BoxShape.circle, 
      ),
      padding: EdgeInsets.all(16.0),
      width: 160.0,
      height: 160.0, 
    ),
  ),
  width: 320.0,
  height: 240.0,
  color: Colors.grey[300],
);

Manipulando texto

Los siguientes ejemplos muestran cómo especificar fuentes y otros atributos de texto. También muestran cómo transformar cadenas de texto, personalizar el espaciado y crear extractos.

Ajustando el espacio del texto

En CSS se especifica la cantidad de espacio en blanco entre cada letra o palabra dando un valor de longitud para las propiedades de espaciado de letras y de palabras, respectivamente. La cantidad de espacio puede ser en px, pt, cm, em, etc.

En Flutter, especificas el espacio en blanco como pixeles lógicos (valores negativos están permitidos) para las propiedades letterSpacing y wordSpacing de un TextStyle hijo de un widget Text.

<div class="greybox">
  <div class="redbox">
    Lorem ipsum
  </div>
</div>

.greybox {
  background-color: #e0e0e0; /* grey 300 */
  width: 320px;
  height: 240px;
  font: 900 24px Roboto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.redbox {
  background-color: #ef5350; /* red 400 */
  padding: 16px;
  color: #ffffff;
  letter-spacing: 4px; 
}
var container = Container( // grey box
  child: Center(
    child: Container( // red box
      child: Text(
        "Lorem ipsum",
        style: TextStyle(
          color: Colors.white,
          fontSize: 24.0,
          fontWeight: FontWeight.w900,
          letterSpacing: 4.0, 
        ),
      ),
      decoration: BoxDecoration(
        color: Colors.red[400],
      ),
      padding: EdgeInsets.all(16.0),
    ),
  ),
  width: 320.0,
  height: 240.0,
  color: Colors.grey[300],
);

Haciendo cambios de formato en línea

Un widget Text te permite mostrar texto con las mismas características de formato. Para mostrar texto que use múltiples estilos (en este ejemplo, una simple palabra con énfasis), usa en su lugar un widget RichText. Su propiedad text puede especificar uno o más widgets TextSpan a los cuales pueden ser estilizados individualmente.

En el siguiente ejemplo, “Lorem” está en un widget TextSpan con el estilo de texto predeterminado (heredado), y “ipsum” está en un TextSpan separado con estilo personalizado.

<div class="greybox">
  <div class="redbox">
    Lorem <em>ipsum</em> 
  </div>
</div>

.greybox {
  background-color: #e0e0e0; /* grey 300 */
  width: 320px;
  height: 240px;
  font: 900 24px Roboto; 
  display: flex;
  align-items: center;
  justify-content: center;
}
.redbox {
  background-color: #ef5350; /* red 400 */
  padding: 16px;
  color: #ffffff;
}
 .redbox em {
  font: 300 48px Roboto;
  font-style: italic;
} 
var container = Container( // grey box
  child: Center(
    child: Container( // red box
      child:  RichText(
        text: TextSpan(
          style: bold24Roboto,
          children: <TextSpan>[
            TextSpan(text: "Lorem "),
            TextSpan(
              text: "ipsum",
              style: TextStyle(
                fontWeight: FontWeight.w300,
                fontStyle: FontStyle.italic,
                fontSize: 48.0,
              ),
            ),
          ],
        ),
      ), 
      decoration: BoxDecoration(
        backgroundColor: Colors.red[400],
      ),
      padding: EdgeInsets.all(16.0),
    ),
  ),
  width: 320.0,
  height: 240.0,
  color: Colors.grey[300],
);

Creación de extractos de texto

Un extracto muestra la línea(s) iniciales de un párrafo de texto y maneja el desbordamiento de texto, a menudo usando puntos suspensivos. En HTML/CSS un extracto no puede ser más largo que una línea. Truncar después de múltiples líneas requiere algo de código JavaScript.

En Flutter, use la propiedad maxLines de un widget Text para especificar el número de líneas para incluir en un extracto, y la propiedad overflow para manejar el desbordamiento del texto.

<div class="greybox">
  <div class="redbox">
    Lorem ipsum dolor sit amet, consec etur
  </div>
</div>

.greybox {
  background-color: #e0e0e0; /* grey 300 */
  width: 320px;
  height: 240px;
  font: 900 24px Roboto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.redbox {
  background-color: #ef5350; /* red 400 */
  padding: 16px;
  color: #ffffff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap; 
}
var container = Container( // grey box
  child: Center(
    child: Container( // red box
      child: Text(
        "Lorem ipsum dolor sit amet, consec etur",
        style: bold24Roboto,
        overflow: TextOverflow.ellipsis,
        maxLines: 1, 
      ),
      decoration: BoxDecoration(
        backgroundColor: Colors.red[400],
      ),
      padding: EdgeInsets.all(16.0),
    ),
  ),
  width: 320.0,
  height: 240.0,
  color: Colors.grey[300],
);