Introducción a HTML y CSS

Versión para imprimir.

por Gilberto Pacheco Gallegos

Instrucciones de navegación

1. SGML

Versión para imprimir.

En esta lección se presenta el lenguaje SGML.

A. SGML

  • Es un lenguaje que consta de texto y marcas, también conocidas como etiquetas.

  • Las marcas Inician con el caracter < y terminan con >. Indican como desplegar el texto; por ejemplo, el texto entre <h1> y </h1> resalta más.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Ejemplo</title>
</head>
<body>
 <h1>Ejemplo</h1>
 <p>Hola mundo.👶</p>
</body>
</html>

B. DOCTYPE

  • Es una etiqueta que define las etiquetas permitidas en un documento y sus características.

  • Es la marca inicial de un archivo SGML y para algunos navegadores debe ser la primera línea del archivo.

  • Aparte de HTML hay otros tipos de documentos; por ejemplo SVG.

Ejemplo

<!DOCTYPE html>

Solo para los más rudos

C. Comentario

  • Inicia con <!-- y termina con -->.

  • Puede ocupar más de un renglón.

  • No puede llevar 2 guiones seguidos (--).

  • No es procesado por el lenguaje.

  • No se despliega en la página.

  • Permite añadir información para entender mejor el código.

  • Normalmente se pone al final de la línea que explican o una línea antes.

Ejemplo

<!DOCTYPE html>
<!--
 Comentario acerca de html. 
-->
<html lang="es">
<head>
 <meta charset="UTF-8"><!--meta-->
</html>

D. Texto

  • El contenido y otras partes de la página se representan con texto.

  • La forma de mostrar el texto se puede cambiar usando marcas.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
❤Este texto es el contenido 📖 de
la página!!!!

E. Elemento

  • Es un objeto que representa una forma de procesar el texto.

  • Normalmente se indican usando marcas.

  • Cada elemento tiene asociado un tipo, que representa su forma de procesamiento.

  • Cada tipo de elemento tiene un funcionamiento preestablecido por el navegador, aunque también es posible crear elementos personalizados.

  • El tipo es la primera palabra de la etiqueta.

Ejemplo

<!DOCTYPE html>
<!-- Elemento de tipo html-->
<html lang="es">
<!-- Elemento de tipo head-->
<head>
 <!-- Elemento de tipo meta-->
 <meta charset="UTF-8">
</head>
</html>

F. Atributos

  • Los elementos tienen preestablecidas características llamadas atributos.

  • Cada atributo tiene asociado un nombre y un valor.

  • Los atributos tienen valores predeterminados que se pueden modificar en el código.

  • Los atributos se colocan en una etiqueta después del tipo de elemento.

  • Se coloca el nombre del atributo, seguido por el signo =, seguido por el valor entre comillas (").

  • Hay atributos que solo pueden valer true o false, también llamados booleanos. En este caso, solo se pone el nombre del atributo y se asume que vale true; cuando valen false, simplemente no se ponen.

  • Hay un atributo especial, llamado id, que pueden definir todos los elementos y los identifica de forma única, para HTML, CSS y JavaScript. Su valor no se puede repetir en ningún otro elemento del documento.

Ejemplo

<!DOCTYPE html>
<!--
 El atributo
  id
   No se puede repetir en el
   documento y vale
    raíz

 El atributo
  lang
   tiene el valor
    es

 El atributo booleano
  hidden
   tiene el valor
    true
-->
<html id="raíz" lang="es" hidden>
</html>

G. Elemento con contenido

  • Lleva:

    • tipo,

    • atributos (opcionalmente) y

    • contenido (opcionalmente), que incluye texto y más etiquetas.

  • Se escribe usando 2 tipos de etiquetas:

    Etiqueta Inicial

    Inicia la definición del elemento.

    Lleva el tipo y opcionalmente los atributos.

    Etiqueta Final o de Cierre

    Termina la definición del elemento.

    Inicia con / y luego el tipo del elemento que cierra.

  • El contenido se coloca entre la etiquetas inicial y final.

  • El doctype determina si un elemento lleva contenido.

Ejemplo

<!DOCTYPE html>
<!--
 html es un elemento con contenido.
 Puede contener comentarios, otros
 elementos y texto.
-->
<html lang="es"><!--Inicia html-->
<!--
 head es contenido de html.
 También es elemento con contenido.
-->
<head> <!-- Inicia head -->
 <!--
  meta es contenido de head.
  No es un elemento con contenido.
 -->
 <meta charset="UTF-8">
</head> <!-- Termina head -->
💪Este texto es contenido de html.
</html><!-- Termina html -->

H. Elemento sin contenido

  • Lleva:

    • tipo

    • atributos (opcionalmente)

  • Se escribe usando solo una etiqueta inicial.

  • El doctype determina si un elemento no lleva contenido.

Ejemplo

<!DOCTYPE html>
<!-- 
 meta es un tipo de elemento sin
 contenido.
-->
<meta charset="UTF-8">
<meta name="viewport"
  content="width=device-width">
<!-- 
 br es un tipo de elemento sin
 contenido.
-->
<br>

I. Elemento padre

  • Un elemento es padre de todos los textos, comentarios, y elementos que formen parte de su contenido.

Ejemplo

<!DOCTYPE html>
<!--
 El elemento html es padre de los
 elementos head y body.
-->
<html lang="es">
<!--
 El elemento head es padre de los
 2 elementos meta y del title.
-->
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Ejemplo</title>
</head>
<!--
 El elemento body es padre de los
 elementos h1 y p.
-->
<body>
 <h1>Ejemplo</h1>
 <p>Hola mundo.👶</p>
</body>
</html>

J. Elemento hijo

  • Un elemento es hijo de otro elemento si pertenece al contenido de este último.

Ejemplo

<!DOCTYPE html>
<!--
 El elemento html no es hijo de
 nadie.
-->
<html lang="es">
<!--
 El elemento head es hijo del
 elemento html.
-->
<head>
 <!--
  Los 2 elementos meta y el title
  son hijos del elemento head.
 -->
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Ejemplo</title>
</head>
<!--
 El elemento body es hijo del
 elemento html.
-->
<body>
 <!--
  Los elementos h1 y p son hijos
  del elemento body.
 -->
 <h1>Ejemplo</h1>
 <p>Hola mundo.👶</p>
</body>
</html>

K. Resumen

  • En esta lección se definieron los siguientes conceptos:

    • SGM.

    • DOCTYPE.

    • Comentario de SGML.

    • Texto.

    • Elemento.

    • Atributo.

    • Elemento con contenido.

    • Elemento sin contenido.

    • Elemento padre.

    • Elemento hijo.

2. Introducción a HTML

Versión para imprimir.

En esta lección se introduce el doctype HTML.

A. Ejemplo básico

  • Este ejemplo muestra la estructura básica de un archivo HTML.

  • En esta lección se explica dicha estructura.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Hola Mundo</title>
</head>
<body>
 👽 ¡Hola Mundo!
</body>
</html>

B. El elemento html

  • El elemento html representa una página. Es el elemento principal. Solo puede haber uno de estos elementos en un archivo.

  • El elemento body tiene 2 elementos hijos: head y body.

  • El atributo lang indica el código del idioma del documento y se aconseja anotarlo en todos los documentos.

Ejemplo

<html lang="es">
<head>
 ...
</head>
<body>
 👽 ¡Hola Mundo!
</body>
</html>

Solo para los más rudos

C. El elemento head

  • El elemento head define la forma de procesar el archivo.

  • Es uno de los elementos hijos de html.

Ejemplo

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Hola Mundo</title>
</head>

Solo para los más rudos

D. Codificación de caracteres

  • Los caracteres son los diferentes símbolos de comunicación que puede usar una computadora, por ejemplo: letras, dígitos, signos de puntuación o emojis.

  • La codificación de un archivo es asignar a cada caracter del archivo una combinación de varios 1 y 0.

  • El elemento meta define información sobre el archivo, también conocida como metadato.

  • El atributo charset define la codifcación del archivo.

  • El estándar UTF-8 es un sistema de codificación para muchos idiomas del mundo entero y está definido en https://home.unicode.org/.

Ejemplo

<meta charset="UTF-8">

Solo para los más rudos

E. El metadato viewport

  • El metadato viewport indica como manejar la pantalla en navegadores de dispositivos móviles.

  • Si no se pone esta etiqueta y la página se muestra en un navegador móvil, aparece reducida en tamaño.

  • También se usa el elemento meta.

  • El atributo name permite definir un metadato.

  • El atributo content permite definir el valor de un metadato.

  • El content width indica el ancho de la página en dispositivos móviles.

  • El valor device-width indica que el ancho de la página en dispositivos móviles es el ancho del dispositivo.

Ejemplo

<meta name="viewport"
  content="width=device-width">

F. El elemento title

  • El elemento con contenido title define el título de la página. No se muestra en el contenido de la página, sino en las pestañas o en las barras de título de las ventanas que muestran la página.

Ejemplo

<title>Hola Mundo</title>

Solo para los más rudos

G. El elemento body

  • El elemento body define el contenido que se muestra.

Ejemplo

<body>
 👽 ¡Hola Mundo!
</body>

Solo para los más rudos

H. Referencia a caracter

  • Se usa para representar caracteres que son complicados de incluir en el texto, o para evitar que sean interpretados como parte del lenguaje de marcas.

  • Inicia con & y termina con ;

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<body>
 &copy; &lt;
</body>

Solo para los más rudos

I. Resumen

  • En esta lección se revisaron los siguientes elementos:

    • html.

    • head.

    • meta

    • title

    • body

  • También se revisaron los siguientes conceptos:

    • Especificar la codificación de caracteres.

    • Especificar el metadato viewport.

    • Referencias a caracteres.

3. Elementos básicos de HTML

Versión para imprimir.

En esta lección se introducen los elementos básicos de HTML.

A. Ejemplo típico

Este es un ejemplo típico de un archivo HTML.

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>🏡Estructura</title>
</head>
<body>
 <!-- Título en el contenido -->
 <h1>🏡Estructura</h1>
 <!-- Navegación -->
 <nav>
  <!-- Título de sección -->
  <h2>Enlaces</h2>
  <!-- Párrafo -->
  <p>
   <!-- hipervínculo -->
   <a href=" https://google.com "
     target="_blank">Google</a>
  </p>
 </nav>
 <!-- Párrafos -->
 <p>🌎Hola Mundo.</p>
 <p>🧻Más texto.</p>
 <!-- Pie de pagina -->
 <footer>
  <p>
   © 2021
   Gilberto Pacheco Gallegos.
  </p>
 </footer>
</body>
</html>

B. Elementos de fraseo

  • Representa el texto de un documento y los elementos que lo modifican.

  • No implica ninguna jerarquía ni estructura.

  • Se puede colocar dentro de otros elementos que si implican estructura; por ejemplo, párrafos, títulos, tablas, etcétera.

Elementos que son contenido de fraseo

  • a
  • abbr
  • area (si es descendiente de map)
  • audio
  • b
  • bdi
  • bdo
  • br
  • button
  • canvas
  • cite
  • code
  • data
  • datalist
  • del
  • dfn
  • em
  • embed
  • i
  • iframe
  • img
  • input
  • ins
  • kbd
  • label
  • link (si se permite dentro de body)
  • map
  • mark
  • math de MathML
  • meta (si el atributo itemprop está presente)
  • meter
  • noscript
  • object
  • output
  • picture
  • progress
  • q
  • ruby
  • s
  • samp
  • script
  • select
  • slot
  • small
  • span
  • strong
  • sub
  • sup
  • svg de SVG
  • template
  • textarea
  • time
  • u
  • var
  • video
  • wbr
  • elemento personalizado autónomo
  • texto

C. Títulos

  • Son los elementos h1, h2, h3, h4, h5 y h6.

  • Normalmente se muestran separados del resto del texto, con un tipo de letra más grande y en negritas.

  • Representan títulos de secciones.

  • Su contenido es de fraseo.

  • Los elementos tienen una categoría en base a su número, donde h1 es la categoría más alta y h6 es la más baja.

  • Títulos de una misma categoría o mayor definen nuevas secciones.

  • Títulos de una categoría más baja definen subsecciones que son parte de la anterior.

  • Se recomienda que haya un solo h1 en una página y sea el título del documento.

Ejemplo

<h1>🏡Estructura</h1>
<nav>
 <h2>Enlaces</h2>
 ...
</nav>
...

Temas por investigar

Solo para los más rudos

D. El elemento p

  • El elemento p representa un párrafo de un documento.

  • Por defecto se muestra separado 1 renglón del contenido previo y otro del contenido que le sigue.

  • Solo puede llevar contenido de fraseo en su interior.

  • Si encuentra en su interior un elemento no permitido, automáticamente termina el párrafo y el elemento prohibido queda fuera del párrafo.

Ejemplo

<p>🌎Hola Mundo.</p>
<p>🧻Más texto.</p>

Solo para los más rudos

E. Elementos que cierran p

  • address
  • article
  • aside
  • blockquote
  • details
  • div
  • dl
  • fieldset
  • figcaption
  • figure
  • footer
  • form
  • h1
  • h2
  • h3
  • h4
  • h5
  • h6
  • header
  • hgroup
  • hr
  • main
  • menu
  • nav
  • ol
  • p
  • pre
  • section
  • table
  • ul

El elemento p también cierra si no hay más contenido en el elemento padre, el cual no es:

  • a
  • audio
  • del
  • ins
  • map
  • noscript
  • video
  • elemento personalizado autónomo

F. El elemento a

  • Es un elemento de fraseo.

  • Se le conoce como ancla.

  • Cuando tiene el atributo href, representa un hipervínculo. El texto que muestra es su contenido, que debe ser de fraseo.

Atributos

href

URL válida del recurso que muestra. Puede estar rodeada por espacios.

target

El valor _blank Hace que el enlace se abra en otra pestaña.

Ejemplo

<a href=" https://google.com "
  target="_blank">Google</a>

Solo para los más rudos

G. El elemento nav

  • El elemento nav es una sección de la página que contiene enlaces a otras páginas o a otras partes de la misma página.

Ejemplo

<nav>
 <h2>Enlaces</h2>
 <p>
  <a href=" https://google.com "
    target="_blank">Google</a>
 </p>
</nav>

Solo para los más rudos

H. El elemento footer

  • Representa el pie de la página o de una sección.

  • Típicamente contiene información de quien escribió la página o sección, enlaces a documentos relacionados, copyright y cosas similares.

  • Cuando contiene secciones, representan apéndices, índices, acuerdos de licencia y contenidos similares.

  • Es normal poner hipervínculos en su interior sin necesidad de usar elementos nav.

Ejemplo

<footer>
 <p>
  © 2021 Gilberto Pacheco Gallegos.
 </p>
</footer>

Solo para los más rudos

I. Resumen

  • En esta lección se revisaron los siguientes elementos:

    • h1, h2, h3, h4, h5 y h6

    • p

    • a

    • nav

    • footer

    • Elementos de fraseo

    • Elementos que cierran p

4. CSS

Versión para imprimir.

En esta lección se introduce el lenguaje CSS.

A. CSS

  • Las hojas de estilo, también conocidas como Cascade Style Sheets (CSS) permiten definir la apariencia de una página escrita en un lenguaje de marcas.

  • La página oficial de CSS3 está en https://www.w3.org/Style/CSS/

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>CSS</title>
 <style>
  h1 {
   coloryellow;
   background-colorblue;
  }

  p {
   colorwhite;
   background-colorblack;
  }
 </style>
</head>
<body>
 <h1>CSS</h1>
 <p>Este es un ejemplo.</p>
 <p>Aprende CSS.</p>
 <h2>Subsección</h2>
 <p>Juega con colores.</p>
 <footer>
  <p>
   © 2021
   Gilberto Pacheco Gallegos.
  </p>
 </footer>
</body>
</html>

Solo para los más rudos

B. El elemento style

  • El elemento style debe colocarse en el elemento de tipo head y contiene el código CSS3 que define la apariencia de la página.

Ejemplo

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>CSS</title>
 <style>
  h1 {
   coloryellow;
   background-colorblue;
  }

  p {
   colorwhite;
   background-colorblack;
  }
 </style>
</head>
<body>
 ...
</body>
</html>

C. Comentarios

  • Los comentarios inician con /* y terminan con */. Pueden ocupar más de un renglón.

  • Se colocan dentro de un elemento style.

Ejemplo

<style>
 /* Comentario sobre h1.  */
 h1 {
  coloryellow/*Sobre color.*/
  background-colorblue;
 }
</style>

D. Reglas de estilo

selector

Una expresión que permite identificar a uno o varios elementos de HTML.

lista de selectores

Una secuencia de selectores separadas por coma (,).

declaración de propiedad

Una expresión del tipo nombre: valor

lista de declaraciones de propiedades

Una secuencia de declaraciones de propiedades separadas por punto y coma (;) y encerradas entre llaves ({ }).

regla de estilo

Une lista de selectores con una lista de declaraciones de propiedades.

Ejemplo

<style>
 /* Esta es una regla.
  * El selector es h1.
  * Sus propiedades están dentro de
  * las llaves. */
 h1 {
  coloryellow;
  background-colorblue;
 } /* Fin de la primera regla. */

 /* Esta es otra regla.
  * El selector es p.
  * Sus propiedades están dentro de
  * las llaves. */
 p {
  colorwhite;
  background-colorblack;
 } /* Fin de la segunda regla. */
</style>

E. Selector de tipo

  • Una forma simple de selector es el selector de tipo, que consiste en usar el tipo de un elemento. Hace que una regla se aplique a todos los elementos de ese tipo.

  • La definición de una selector de tipo está en https://www.w3.org/TR/selectors-3/#type-selectors

Ejemplo

<head>
 <style>
  /* El selector
   *  h1
   * hace que las propiedades de
   * esta regla se apliquen a todos
   * los elementos de tipo
   *  h1. */
  h1 {
   coloryellow;
   background-colorblue;
  }

  /* El selector
   *  p
   * hace que las propiedades de
   * esta regla se apliquen a todos
   * los elementos de tipo
   *  p. */
  p {
   colorwhite;
   background-colorblack;
  }
 </style>
</head>
<body>
 <!-- Las reglas con el selector
   h1
  se aplican a este elemento. -->
 <body>
  <h1>CSS</h1>
  <!-- Las reglas con el selector
    p
   se aplican a este elemento. -->
  <p>Este es un ejemplo.</p>
  <!-- Las reglas con el selector
    p
   se aplican a este elemento. -->
  <p>Aprende CSS.</p>
  <h2>Subsección</h2>
  <!-- Las reglas con el selector
    p
   se aplican a este elemento. -->
  <p>Juega con colores.</p>
  <footer>
   <!-- Las reglas con el selector
     p
    se aplican a este elemento. -->
   <p>
    © 2021
    Gilberto Pacheco Gallegos.
   </p>
  </footer>
 </body>

F. Propiedades

  • Se declaran con una expresión del tipo

    nombre: valor

Ejemplo

<head>
 <style>
  h1 {
   /* Esta es la propiedad
    *  color.
    * En este caso se aplica
    * a los elementos tipo
    *  h1.
    * Su valor es yellow. */
   coloryellow;
   /* Esta es la propiedad
    *  background-color.
    * En este caso se aplica
    * a los elementos tipo
    *  h1.
    * Su valor es blue. */
   background-colorblue;
  }

  p {
   /* Esta es la propiedad
    *  color.
    * En este caso se aplica
    * a los elementos tipo
    *  p.
    * Su valor es white. */
   colorwhite;
   /* Esta es la propiedad
    *  background-color.
    * En este caso se aplica
    * a los elementos tipo
    *  p.
    * Su valor es black. */
   background-colorblack;
  }
 </style>
</head>
<body>
 <h1>CSS</h1>
 <p>Este es un ejemplo.</p>
 <p>Aprende CSS.</p>
 <h2>Subsección</h2>
 <p>Juega con colores.</p>
 <footer>
  <p>
   © 2021
   Gilberto Pacheco Gallegos.
  </p>
 </footer>
</body>

G. Propiedades personalizadas

  • En CSS3 se pueden definir constantes y usar su valor a lo largo del código CSS.

  • El nombre de la propiedad personalizada debe iniciar con 2 guiones (--).

  • Deben definirse en la regla para el elemento raíz, que en este caso es (html).

  • Para usar el valor, debe colocarse dentro de la expresión var(--propiedad).

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<head>
 <style>
  html {
   --colTextoyellow;
   --colFondoblue;
  }

  h1 {
   colorvar(--colTexto);
   background-color:
    var(--colFondo);
  }

  p {
   colorvar(--colTexto);
   background-colorblack;
  }
 </style>
</head>
<body>
 <h1>CSS</h1>
 <p>Este es un ejemplo.</p>
 <p>Aprende CSS.</p>
 <h2>Subsección</h2>
 <p>Juega con colores.</p>
 <footer>
  <p>
   © 2021
   Gilberto Pacheco Gallegos.
  </p>
 </footer>
</body>

H. Resumen

  • En esta lección se definieron los siguientes conceptos:

    • El elemento style.

    • Comentarios de CSS.

    • Reglas de estilo de CSS.

    • Selector de tipo de CSS.

    • Propiedades de CSS.

    • Propiedades personalizadas de CSS.

5. Propiedades básicas de CSS

Versión para imprimir.

En esta lección se presentan las propiedades básicas de CSS.

A. Fonts

  • Cada símbolo que se puede representar en una familia de fuentes se conoce como glifo o pictograma.

Algunas Familias Básicas

serif
  • Es el tipo de letra que lleva adornos.

  • Cada glifo puede tener un ancho diferente al de los otros de la misma familia.

  • Permite leer cómodamente textos largos.

  • Viene predefinida, pero la familia exacta depende de cada navegador web.

Ejemplo de Serif.

sans-serif
  • Es el tipo de letra que no lleva adornos.

  • Luce más en títulos, textos cortos e interfaces de usuario.

  • Cada glifo puede tener un ancho diferente al de los otros de la misma familia.

  • Viene predefinida, pero la familia exacta depende de cada navegador web.

Ejemplo de Sans Serif.

Solo para los más rudos

B. La propiedad font-family

  • Define el tipo de letra.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>font-family</title>
 <style>
  h1 {
   font-familysans-serif
  }

  p {
   font-familyserif
  }
 </style>
</head>
<body>
 <h1>font-family sans-serif</h1>
 <p>font-family serif.</p>
</body>
</html>

C. Colores en CSS

Colores primarios

Los colores se expresan como una combinación de los colores primarios:

  • Rojo (red en inglés)

  • Verde (green en inglés)

  • Azul (blue en inglés)

Especificación de los colores primarios y transparencia

Estas son algunas formas de expresar los colores primarios en las definiciones que aparecen después:

num_rojo

Valor decimal entre 0 y 255. Indica la cantidad de rojo que lleva un color.

num_verde

Valor decimal entre 0 y 255. Indica indica la cantidad de verde que lleva un color.

num_azul

Valor decimal entre 0 y 255. Indica la cantidad de azul que lleva un color.

num_transp

Valor decimal fraccionario entre 0 y 1. Indica lo transparente que es un color: 0 - totalmente transparente, 1 - totalmente opaco.

rr

Valor de 2 cifras hexadecimales entre 00 y ff. Indica la cantidad de rojo que lleva un color.

gg

Valor de 2 cifras hexadecimales entre 00 y ff. Indica la cantidad de verde que lleva un color.

bb

Valor de 2 cifras hexadecimales entre 00 y ff. Indica la cantidad de azul que lleva un color.

aa

Valor de 2 cifras hexadecimales entre 00 y ff. Indica lo transparente que es un color. 00 - totalmente transparente, ff - totalmente opaco.

Algunas Formas de Expresar Colores en CSS3

transparent

Color transparente.

Nombre del color

Los nombres de colores que se pueden usar están definidos en https://www.w3.org/TR/css-color-3/#html4. y en https://www.w3.org/TR/css-color-3/#svg-color.

Ejemplo:

blue

rgb(num_rojo, num_verde, num_azul)

Representa la mezcla de colores rojo, verde y azul en notación decimal.

Ejemplo:

rgb(155, 255, 43)

rgba(num_rojo, num_verde, num_azul, num_transp)

Representa la mezcla de rojo, verde, azul y transparencia en notación decimal.

Ejemplo:
rgba(155,255,43,0.7)

#rrggbb

Representa la mezcla de colores rojo, verde y azul en notación hexadecimal.

Ejemplo:

#a2fe09

#rrggbbaa

Representa la mezcla de rojo, verde, azul y transparencia en notación hexadecimal.

Ejemplo:
#0b467380

Temas por Investigar

Solo para los más rudos

D. La propiedad color

  • Especificar el color del trazo, por ejemplo, del texto.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Color</title>
 <style>
  h1 {
   colorblue
  }

  p {
   color#005500
  }
 </style>
</head>
<body>
 <h1>Color blue</h1>
 <p>Color #005500.</p>
</body>
</html>

Solo para los más rudos

E. La propiedad background-color

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>background-color</title>
 <style>
  h1 {
   background-coloryellow
  }

  p {
   background-color#aaffaa
  }
 </style>
</head>
<body>
 <h1>background-color yellow</h1>
 <p>background-color #aaffaa.</p>
</body>
</html>

Solo para los más rudos

F. Resumen

  • En esta lección se definieron los siguientes conceptos:

    • Fonts.

    • La propiedad font-family.

    • Colores en CSS

    • La propiedad color

    • La propiedad background-color.

6. La propiedad display

Versión para imprimir.

En esta lección se presenta el concepto de polimorfismo.

A. El elemento div

  • Es un elemento sin significado que agrupa otros elementos.

  • Puede usarse con los atributos class, lang y title para definir la semántica común a un grupo de elementos consecutivos.

  • Puede usarse en un elemento dl para envolver grupos de elementos dt y dd.

  • Se recomienda que el elemento div se utilice como último recurso cuando no se pueda usar ningún otro elemento.

  • El uso de elementos más apropiados propicia una mejor accesibilidad para lectores y un mantenimiento más fácil para los autores.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>div</title>
 <style>
  div {
   colorchocolate;
  }
 </style>
</head>
<body>
 <div>Un div simple.</div>
 <div>Otro div simple.</div>
 <p>Un párrafo simple.</p>
 <p>Otro párrafo simple.</p>
</body>
</html>

Solo para los más rudos

B. El elemento span

  • Es un elemento de fraseo sin significado.

  • Puede usarse con los atributos globales, por ejemplo class, lang o dir.

  • Se recomienda que el elemento span se utilice como último recurso cuando no se pueda usar ningún otro elemento.

  • El uso de elementos más apropiados propicia una mejor accesibilidad para lectores y un mantenimiento más fácil para los autores.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>span</title>
 <style>
  span {
   colormagenta;
  }
 </style>
</head>
<body>
 <p>
  Hola,
  <span>este es un span.</span>
  Más texto
  <span>otro span.</span>
 </p>
 <p>Otro párrafo simple.</p>
</body>
</html>

Solo para los más rudos

C. La propiedad display

  • Indica la forma en que un elemento se depliega.

  • La definición oficial de esta propiedad está en proceso de cambio.

  • El contenido de texto no tiene la propiedad display.

  • Esta propiedad no afecta la semántica de los elementos, pero si puede cambiar como se despliegan.

  • En las diapositivas siguientes se explican algunos de los valores posibles.

D. El valor none

  • El elemento completo, incluyendo todo su contenido, el contenido de su contenido y así sucesivamente no se muestra, incluyendo texto y cajas.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>inline</title>
 <style>
  div {
   displaynone
  }
 </style>
</head>
<body>
 <p>Ahora me ves.</p>
 <div>Ahora no me ves.</div>
</body>
</html>

E. El valor inline

  • Solo contiene elementos de tipo inline, inline-block y texto.

  • De forma predeterminada, los elementos de fraseo como span, em, del, o strong tienen este tipo de despliegue, pero se puede cambiar.

  • El contenido se despliega de forma horizontal, uno tras otro. Si llega al final del elemento padre más próximo que sea block o inline-block, continuá al inicio del siguiente renglón.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>inline</title>
 <style>
  p {
   displayinline;
   colorolive
  }
 </style>
</head>
<body>
 <div>
  El texto es inline.
  El texto es inline.
  El texto es inline.
  El texto es inline.
  El texto es inline.
  <span>El span es inline.</span>
  <p>
   Este párrafo es forzado a ser
   inline.
  </p>
  <em>
   Esto es texto con énfasis.
  </em>
  <strong>
   Esto es texto con énfasis
   fuerte.
  </strong>
  Más texto.
  Más texto.
  Más texto.
  Más texto.
 </div>
</body>
</html>

F. El valor block

  • Contiene elementos de cualquir tipo de despliegue.

  • De forma predeterminada, los elementos de agrupamiento como p, header footer o div tienen este tipo de despliegue, pero se puede cambiar.

  • Si contiene solo elementos de despliegue inline, inline-block y texto, estos se despliegan de forma horizontal uno tras otro, iniciando en la parte superior del elemento. Si llega al final de un renglón, continuá al inicio del siguiente.

  • Si contiene solo elementos de despliegue block, estos se despliegan de forma vertical uno tras otro, utilizando todo el ancho permitido por el elemento que los contiene.

  • Si contiene mezclados elementos inline, inline-block, texto y block, los inline, inline-block y textos consecutivos se agrupan en una caja de tipo block imaginaria y se aplica el despliegue cuando todos los elementos son de tipo block.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>block</title>
 <style>
  div {
   background-coloryellow;
  }
 </style>
</head>
<body>
 <h1>block</h1>
 <p>
  En este ejemplo, body solo
  tiene elementos de bloque.
 </p>
 <p>
  Este párrafo solo tiene contenido
  inline e inline-block.
  <em>Un énfasis inline.</em>
  <button>
   Un botón inline-block,
   inline-block, inline-block
  </button>
  <span>
   Un span inline, inline, inline,
   inline.
  </span>
 </p>
 <div>
  Este div tiene contenido
  mezclado.
  <em>
   Este es un énfasis inline.
  </em>
  <strong>
   Este es un strong inline.
  </strong>
  <button>
   Este es un botón inline-block
  </button>
  <p>
   Este párrafo solo contiene
   inline e inline-block.
   <em>Un énfasis inline.</em>
   <button>
    Un botón inline-block
   </button>
   <span>Un span inline.</span>
  </p>
 </div>
</body>
</html>

G. El valor inline-block

  • El nombre de este tipo de despliegue está por cambiar.

  • De forma predeterminada, los elementos de formulario como button, o input tienen este tipo de despliegue, pero se puede cambiar.

  • Su contenido sigue las reglas de un display block.

  • Sus padres lo ven como un elemento inline, pero el elemento ocupa un solo renglón del elemento padre más próximo que sea block o inline-block.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>inline-block</title>
 <style>
  span {
   displayinline-block;
   background-coloryellow;
  }
 </style>
</head>
<body>
 <p>
  Texto, texto, texto
  <span>
   Este es un span forzado a ser
   inline-block, inline-block,
   inline-block, inline-block.
  </span>
  <button>
   Este es un botón inline-block,
   inline-block, inline-block.
  </button>
 </p>
</body>
</html>

H. Resumen

  • En esta lección se introdujeron los siguientes conceptos:

    • El elemento div.

    • El elemento span.

    • La propiedad display.

    • El valor none.

    • El valor inline.

    • El valor block.

    • El valor inline-block.

7. El modelo de cajas

Versión para imprimir.

En esta lección se presenta el concepto de excepciones y como procesarlas.

A. Longitudes en CSS

  • Hay algunas propiedades que expresan tamaños o distancias. Por ejemplo:

    font-size

    Indica el tamaño de letra.

    Los valores son números decimales, que opcionalmente son fraccionales y son seguidos sin espacio por las unidades de medición. Ejemplos: 3em, 2.4rem.

    El cero se puede expresar sin unidades; por ejemplo: 0.

    Algunas unidades de medición son:

    em

    La altura de un renglón de texto, usando el tamaño de letra del elemento.

    rem

    La altura de un renglón de texto, usando el tamaño de letra del elemento raíz (que en HTML, es el elemento html).

    vh

    1% de la altura del puerto de visión (la ventana).

    vw

    1% del ancho del puerto de visión (la ventana).

    %

    Porcentaje del espacio que el elemento padre permite que sus hijos ocupen.

    px

    Pixeles.

B. El modelo de cajas

Margen
Borde
Relleno
contenido
Margen

Es un espacio transparente que separa un elemento de otro.

Borde

Es una línea (que puede ser una figura con adornos) alrededor de un elemento.

Relleno

Es una espacio entre el contenido y el borde. Su color de fondo es el mismo que el color de fondo del contenido.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Modelo de cajas</title>
 <style>
  div {
   margin1.5rem;
   borderthick solid burlywood;
   background-colorgreenyellow;
  }
 </style>
</head>
<body>
 <div>Contenido</div>
</body>
</html>

C. Margen (margin)

  • Se pueden especificar con las siguientes propiedades:

    margin-top

    Solo especifica el tamaño del margen en la parte superior de la caja.

    Ejemplo:

    margin-top: 3vh

    margin-bottom

    Solo especifica el tamaño del margen en la parte inferior de la caja.

    Ejemplo:

    margin-bottom: 50%

    margin-left

    Solo especifica el tamaño del margen en el lado izquierdo de la caja.

    Ejemplo:

    margin-left: 8px

    margin-right

    Solo especifica el tamaño del margen en el lado derecho de la caja.

    Ejemplo:

    margin-right: 3vw

    margin: tamaño

    Especifica el mismo tamaño de margen arriba, abajo, a la izquierda y a la derecha.

    Ejemplo:

    margin: 1em
    El margen mide 1 renglón en todas las direcciones alrededor del elemento.

    margin: tam_vertical tam_horizontal

    tam_vertical es el tamaño de los márgenes superior e inferior.

    tam_horizontal es el tamaño de los márgenes izquierdo y derecho.

    Ejemplo:

    margin: 1em 2em
    El margen mide 1 renglón arriba y abajo, 2 renglones a la izquierda y derecha.

    margin: tam_arr tam_der tam_ab tam_izq

    tam_arr es el tamaño del márgen superior.

    tam_der es el tamaño del márgen derecho.

    tam_ab es el tamaño del márgen inferior.

    tam_izq es el tamaño del márgen izquierdo.

    Ejemplo:

    margin: 3em 2em 4em 1em
    El margen mide 3 renglones arriba, 2 a la derecha, 4 abajo y 1 a la izquierda.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Márgenes</title>
 <style>
  h1 {
   margin-top0.5rem;
   margin-left1rem;
   margin-bottom1.5rem;
   margin-right2rem;
   background-colorcyan;
  }

  p {
   margin0.5rem 2rem;
   background-coloryellow;
  }

  div {
   margin1rem;
   background-colorred;
  }

  footer {
   margin:
    0.5rem 1rem 3rem 2rem;
   background-color:
    yellowgreen;
  }
 </style>
</head>
<body>
 <h1>Márgenes</h1>
 <p>Párrafo</p>
 <div>Div</div>
 <footer>Footer</footer>
 <hr>
</body>
</html>

D. Relleno (padding)

  • Se puede especificar con las siguientes propiedades:

    padding-top

    Solo especifica el tamaño del relleno en la parte superior de la caja.

    Ejemplo:

    padding-top: 3vh

    padding-bottom

    Solo especifica el tamaño del relleno en la parte inferior de la caja.

    Ejemplo:

    padding-bottom: 50%

    padding-left

    Solo especifica el tamaño del relleno en el lado izquierdo de la caja.

    Ejemplo:

    padding-left: 8px

    padding-right

    Solo especifica el tamaño del relleno en el lado derecho de la caja.

    Ejemplo:

    padding-right: 3vw

    padding: tamaño

    Especifica el mismo tamaño de relleno arriba, abajo, a la izquierda y a la derecha.

    Ejemplo:

    padding: 1em
    El relleno mide 1 renglón en todas las direcciones alrededor del elemento.

    padding: tam_vertical tam_horizontal

    tam_vertical es el tamaño de los rellenos superior e inferior.

    tam_horizontal es el tamaño de los rellenos izquierdo y derecho.

    Ejemplo:

    padding: 1em 2em
    El relleno mide 1 renglón arriba y abajo, 2 renglones a la izquierda y derecha.

    padding: tam_arr tam_der tam_ab tam_izq

    tam_arr es el tamaño del relleno superior.

    tam_der es el tamaño del relleno derecho.

    tam_ab es el tamaño del relleno inferior.

    tam_izq es el tamaño del relleno izquierdo.

    Ejemplo:

    padding: 3em 2em 4em 1em
    El relleno mide 3 renglones arriba, 2 a la derecha, 4 abajo y 1 a la izquierda.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Relleno</title>
 <style>
  h1 {
   padding-top0.5rem;
   padding-left1rem;
   padding-bottom1.5rem;
   padding-right2rem;
   background-colorcyan;
  }

  p {
   padding0.5rem 2rem;
   background-coloryellow;
  }

  div {
   padding1rem;
   background-colorred;
  }

  footer {
   padding:
    0.5rem 1rem 3rem 2rem;
   background-color:
    yellowgreen;
  }
 </style>
</head>
<body>
 <h1>Relleno</h1>
 <p>Párrafo</p>
 <div>Div</div>
 <footer>Footer</footer>
</body>
</html>

E. Borde (border)

Partes de un Borde

Ancho

Puede expresarse como un tamaño o con alguno de estos valores:

thin
Borde delgado.
medium
Borde de ancho mediano.
thick
Borde grueso.

Si no se pone, su valor por omisión es: medium.

Estilo

Puede expresarse con alguno de estos valores:

none

Sin borde.

dotted

El borde es una serie de puntos redondos.

dashed

El borde es una serie de guiones de esquinas cuadradas.

solid

El borde es una sola línea sólida.

double

El borde consiste en 2 líneas sólidas paralelas con espacio entre ellas.

La suma del ancho de las líneas y espacio debe ser igual al ancho del borde.

groove

El borde parece como si estuviera tallado dentro de la superficie.

ridge

El borde parece como si saliera de la superficie.

inset

Parece como si el contenido dentro del borde estuviera hundido en la superficie.

outset

Parece como si el contenido dentro del borde saliera de la superficie.

Si no se pone, su valor por omisión es: none.

Color

Se especifica como un color cualquiera.

Si no se pone, su valor por omisión es el color del texto del elemento.

Propiedades para Bordes

Estilo Detallado

border-top-width

Ancho del borde en la parte superior de la caja.

border-top-style

Estilo del borde en la parte superior de la caja.

border-top-color

Color del borde en la parte superior de la caja.

border-bottom-width

Ancho del borde en la parte inferior de la caja.

border-bottom-style

Estilo del borde en la parte inferior de la caja.

border-bottom-color

Color del borde en la parte inferior de la caja.

border-left-width

Ancho del borde en el lado izquierdo de la caja.

border-left-style

Estilo del borde en el lado izquierdo de la caja.

border-left-color

Color del borde en el lado izquierdo de la caja.

border-right-width

Ancho del borde en el lado derecho de la caja.

border-right-style

Estilo del borde en el lado derecho de la caja.

border-right-color

Color del borde en el lado derecho de la caja.

Combinando las Partes del Borde

Combina las tres partes de un borde. Las partes pueden ir en cualquier orden y 1 o 2 de los valores pueden faltar, en cuyo caso se toman los valores por omisión (medium, none y color actual).

border-top

Ancho, estilo y color del borde en la parte superior de la caja.

border-bottom

Ancho, estilo y color del borde en la parte inferior de la caja.

border-left

Ancho, estilo y color del borde en el lado izquierdo de la caja.

border-right

Ancho, estilo y color del borde en el lado derecho de la caja.

border

Ancho, estilo y color del borde único en las partes izquierda, derecha, superior e inferior de la caja.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Bordes</title>
 <style>
  h1 {
   border-top-widththin;
   border-top-stylesolid;
   border-top-colorcyan;
   border-left:
    medium dashed red;
   border-right:
    thick dotted green;
   border-bottom:
    thick double blue
  }

  nav {
   borderthick groove cyan
  }

  p {
   borderthick ridge pink
  }

  div {
   borderthick inset yellowgreen
  }

  footer {
   borderthick outset orange
  }
 </style>
</head>
<body>
 <h1>Bordes</h1>
 <nav>Groove</nav>
 <p>Ridge</p>
 <div>Inset</div>
 <footer>Outset</footer>
</body>
</html>

F. Esquinas redondas (border-radius)

  • Las esquinas de la caja pueden ser redondas aunque no lleven borde.

    border-top-right-radius

    Tamaño del radio de la esquina superior derecha de la caja.

    border-top-left-radius

    Tamaño del radio de la esquina superior izquierda de la caja.

    border-bottom-right-radius

    Tamaño del radio de la esquina inferior derecha de la caja.

    border-bottom-left-radius

    Tamaño del radio de la esquina inferior izquierda de la caja.

    border-radius: tam

    tam es el tamaño del radio de las 4 esquinas de la caja.

    border-radius: tam_arrizq_abder tam_arrder_abizq

    tam_arrizq_abder es el tamaño del radio de las esquinas superior izquierda e inferior derecha de la caja.

    tam_arrder_abizq es el tamaño del radio de las esquinas superior derecha e inferior izquierda de la caja.

    border-radius: tam_arrizq tam_arrder_abizq tam_abder

    tam_arrizq es el tamaño del radio de la esquina superior izquierda de la caja.

    tam_arrder_abizq es el tamaño del radio de las esquinas superior derecha e inferior izquierda de la caja.

    tam_abder es el tamaño del radio de las esquinas inferior derecha de la caja.

    border-radius: tam_arrizq tam_arrder tam_abder tam_abizq

    tam_arrizq es el tamaño del radio de la esquina superior izquierda de la caja.

    tam_arr es el tamaño del radio de las esquinas superior derecha de la caja.

    tam_abder es el tamaño del radio de las esquinas inferior derecha de la caja.

    tam_abizq es el tamaño del radio de la esquina inferior izquierda de la caja.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width,
       initial-scale=1.0">
 <title>border-radius</title>
 <style>
  body {
   color:yellow
  }

  h1 {
   background-colorblue;
   border-top-right-radius10px;
   border-top-left-radius5px;
   border-bottom-right-radius:
    20px;
   border-bottom-left-radius:
    2rem
  }

  div {
   background-colorroyalblue;
   padding0.5rem 1rem;
   border-radius30px
  }

  p {
   background-colorblueviolet;
   padding0.5rem 1.5rem;
   border-radius:
    10px 20px 30px 40px;
  }
 </style>
</head>
<body>
 <h1>border-radius</h1>
 <div>Esquinas</div>
 <p>Redondas</p>
</body>
</html>

G. Propiedades para tamaños

width

Ancho de un elemento. Se indica usando un número decimal, opcionalmente fraccionario, seguido de la unidad.

Solo aplica para para los elementos con display block o inline-block.

Ejemplo:

width: 100%

height

Altura de un elemento. Se indica usando un número decimal, opcionalmente fraccionario, seguido de la unidad.

Solo aplica para para los elementos con display block o inline-block.

Ejemplo:

height: 3em

box-sizing

Indica como calcular el tamaño de un componente. Aplica para las propiedades width y height.

Los valores que puede tomar esta propiedad son:

content-box

El tamaño es solo el tamaño del contenido. Cuando en se especifica esta propiedad para un elemento, este es el valor que se utiliza (valor por omisión).

border-box

El tamaño incluye el tamaño del contenido, más el espacio ocupado por los bordes y el relleno.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width,
       initial-scale=1.0">
 <title>box-sizing</title>
 <style>
  main {
   width50%;
   height15rem;
   background-colororange;
   padding-top1rem;
   padding-bottom1rem;
  }

  h1 {
   width100%;
   background-colorlightgreen;
   margin0;
   font-size1rem;
   padding1em;
   borderthick solid green;
  }

  nav {
   box-sizingcontent-box;
   width100%;
   background-colorpink;
   padding1em;
   borderthick solid red;
  }

  p {
   box-sizingcontent-box;
   width100%;
   background-colorviolet;
   margin0;
  }

  div {
   box-sizingborder-box;
   width100%;
   background-colorlightblue;
   padding1em;
   borderthick solid blue;
  }
 </style>
</head>
<body>
 <main>
  <h1>por omisión</h1>
  <nav>content-box</nav>
  <p>content-box 2</div>
  <div>border-box</div>
 </main>
</body>
</html>

H. Resumen

  • En esta lección se presentaron los siguientes conceptos:

    • Longitudes en CSS.

    • El modelo de cajas.

    • Márgenes.

    • Relleno.

    • Bordes.

    • Esquinas redondas.

    • Propiedades para tamaños.

8. Posicionamiento

Versión para imprimir.

En esta lección se presenta el concepto de posicionamiento.

A. Propiedades de posicionamiento

  • Es posible cambiar el modelo de cajas, usando un método que permita controlar por coordenadas la posición de algunos elementos dentro de la ventana. Para ello se utilizan las siguientes propiedades:

    position

    Controla la forma de colocar un elemento en la ventana.

    Los valores que puede tomar se explican a lo largo de esta lección y son:

    static

    Es el posicionamiento normal y no usa las propiedades de posicionamiento.

    fixed

    Es relativo a la ventana del navegador.

    relative

    Es relativo a la posición normal del elemento.

    absolute

    Es relativo a la posición de su ancestro más inmediato que no tenga posicionamiento static.

    sticky

    Usa posicionamiento relative mientras el elemento está en el área visible de la ventana y se vuelve fixed cuando sale del área visible de la ventana.

    top

    Posición de la parte superior del elemento con respecto a la posición original (posicionamiento relative) o al elemento contenedor.

    bottom

    Posición de la parte inferior del elemento con respecto a la posición original (posicionamiento relative) o al elemento contenedor.

    left

    Posición de la parte izquierda del elemento con respecto a la posición original (posicionamiento relative) o al elemento contenedor.

    right

    Posición de la parte izquierda del elemento con respecto a la posición original (posicionamiento relative) o al elemento contenedor.

    width

    Ancho de un elemento. Se indica usando un número decimal, opcionalmente fraccionario, seguido de la unidad.

    height

    Altura de un elemento. Se indica usando un número decimal, opcionalmente fraccionario, seguido de la unidad.

    z-index

    Los elementos se pueden colocar en capas y ocultarse unos a otros. Un elemento se coloca sobre los elementos hermanos con posicionamiento no static que aparecen antes en el texto. La propiedad z-index se usa para cambiar ese orden. El número z-index más grande está arriba y tapa a todos los que tienen un valor menor. Empieza desde 1.

B. El posicionamiento fixed

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>
  Posicionamiento fixed
 </title>
 <style>
  span {
   positionfixed;
   top0;
   right0;
   background-coloryellow;
  }
 </style>
</head>
<body>
 <h1>
  Posicionamiento
  <span>fixed</span>
 </h1>
</body>
</html>

C. El posicionamiento relative

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>
  Posicionamiento relative
 </title>
 <style>
  span {
   positionrelative;
   top1rem;
   left1rem;
   background-coloryellow;
  }
 </style>
</head>
<body>
 <h1>
  Posicionamiento
  <span>relative</span>
 </h1>
</body>
</html>

D. El posicionamiento absolute

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>
  Posicionamiento absolute
 </title>
 <style>
  h1 {
   positionabsolute;
   bottom0;
   height6rem;
   left2rem;
   right2rem;
   background-coloryellow;
  }

  p {
   positionrelative;
   background-colorchartreuse
  }

  footer {
   positionfixed;
   top0;
   right0;
   width10rem;
   background-coloryellow;
  }

  span {
   positionabsolute;
   top0;
   left0;
   background-colorcyan;
  }
 </style>
</head>
<body>
 <h1>
  Posicionamiento
  <span>absolute (h1)</span>
 </h1>
 Bla, bla, bla
 <p>
  Párrafo relative con
  <span>absolute (p)</span>
 </p>
 <div>
  Este div contiene
  <span>absolute (div)</span>
 </div>
 <footer>
  Este footer lleva otro
  <span>absolute (footer)</span>
 </footer>
</body>
</html>

E. El posicionamiento sticky

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>
  Posicionamiento sticky
 </title>
 <style>
  h1 {
   /* Algunas versiones de Safari
    * no soportan "sticky", pero sí
    * "-webkit-sticky".  */
   position: -webkit-sticky;
   positionsticky;
   top1rem;
   background-coloryellow;
  }
 </style>
</head>
<body>
 <h1>Posicionamiento sticky</h1>
 <ol>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
  <li>X</li>
 </ol>
</body>
</html>

F. Resumen

  • En esta lección se revisaron los siguientes conceptos:

    • Propiedades de posicionamiento

    • El posicionamiento fixed

    • El posicionamiento relative

    • El posicionamiento absolute

    • El posicionamiento sticky

9. Selectores de CSS

Versión para imprimir.

En esta lección se presentan algunos selectores de CSS.

A. El selector *

  • Selecciona todos los elementos.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Selector *</title>
 <style>
  * {
   /* Texto centrado. */
   text-aligncenter;
  }
 </style>
</head>
<body>
 <h1>Selector *</h1>
 <p>Hola.</p>
</body>
</html>

B. El selector #identificador

  • Selecciona el valor del atributo id.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>
  Selector #identificador
 </title>
 <style>
  /* Seleciona el elemento con
   *  id="neg" */
  #neg {
   /* negritas */
   font-weightbold;
  }

  /* Seleciona el elemento de tipo
   *  p
   * con
   *  id="otro" */
  p#otro {
   /* mayúsculas */
   text-transformuppercase;
  }

  /* Seleciona el elemento de tipo
   *  h1
   * con
   *  id="chas".
   * No se aplica porque el único
   * elemento con
   *   id="chas"
   * es de tipo
   *    p */
  h1#chas {
   colorgreen;
  }
 </style>
</head>
<body>
 <h1>Selector #identificador</h1>
 <p>Uno.</p>
 <p id="chas">Dos.</p>
 <p>Tres.</p>
 <p id="otro">Cuatro.</p>
</body>
</html>

C. El selector .clase

  • Seleciona los elementos cuyo atributo class contenga el identificador después del punto (.).

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Selector .clase</title>
 <style>
  /* Seleciona los elementos cuyo
   * atributo
   *  class
   * contenga el identificador
   *  azu */
  .azu {
   colorblue;
  }

  /* Seleciona los elementos cuyo
   * atributo
   *  class
   * contenga los identificadores
   *  ama y azu */
  .ama.azu {
   /* letra itálica */
   font-styleoblique;
  }

  /* Seleciona los elementos tipo
   *  p
   * cuyo atributo
   *  class
   * contenga el identificador
   *  ama */
  p.ama {
   background-coloryellow;
  }

  /* Seleciona los elementos tipo
   *  p
   * cuyo atributo
   *  class
   * contenga los identificadores
   *  ama y ver */
  p.ama.ver {
   /* Alínea el texto al final de
    * la línea. */
   text-alignend;
  }
 </style>
</head>
<body>
 <h1 class="ama azu">
  Selector .clase
 </h1>
 <p class="ver azu ama">
  Uno.
 </p>
 <p class="azu">Dos.</p>
 <p>Tres.</p>
 <p class="ama">Cuatro.</p>
 <p class="ama ver">Cinco.</p>
 <footer class="azu">
  <p>
   © 2021
   Gilberto Pacheco Gallegos.
  </p>
 </footer>
</body>
</html>

D. El selector sel1 > sel2

  • Seleciona los elementos que cumplan con el selector de la derecha y que sean hijos directos de los elementos que cumplan con el seletor de la izquierda.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>
  Selector sel1 &gt; sel2
 </title>
 <style>
  /* Selecciona todos los
   *  em
   * que sean hijos directos de
   *  p */
  p>em {
   background-coloryellow;
  }
 </style>
</head>
<body>
 <h1>
  Selector
  <em>sel1</em>
  <strong>&gt;</strong>
  <em>sel2</em>
 </h1>
 <p>
  <strong>
   Énfasis fuerte.
  </strong>
  <em>Énfasis.</em>
  Más texto.
  <span>
   <em>Otro énfasis.</em>
   <strong>
    Otro énfasis fuerte.
   </strong>
   <span>
    <em>Hola.</em>
    <strong>Adios.</strong>
   </span>
  </span>
 </p>
 <footer>
  <p>
   <em>© 2021</em>
   Gilberto Pacheco Gallegos.
  </p>
 </footer>
</body>
</html>

E. El selector sel1 sel2

  • Seleciona los elementos que cumplan con el selector de la derecha y que sean descendientes en cualquier nivel de anidamiento de los elementos que cumplan con el seletor de la izquierda.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>
  Selector sel1 sel2
 </title>
 <style>
  /* Selecciona todos los
   *  em
   * que sean descendientes en
   * cualquier nivel de anidamiento
   * de
   *  p */
  p em {
   background-coloryellow;
  }
 </style>
</head>
<body>
 <h1>
  Selector
  <em>sel1</em>
  <em>sel2</em>
 </h1>
 <p>
  <strong>
   Énfasis fuerte.
  </strong>
  <em>Énfasis.</em>
  Más texto.
  <span>
   <em>Otro énfasis.</em>
   <strong>
    Otro énfasis fuerte.
   </strong>
   <span>
    <em>Hola.</em>
    <strong>Adios.</strong>
   </span>
  </span>
 </p>
 <footer>
  <p>
   <em>© 2021</em>
   Gilberto Pacheco Gallegos.
  </p>
 </footer>
</body>
</html>

F. El selector sel1 + sel2

  • Seleciona los elementos que cumplan con el selector de la derecha y que sean hermanos inmediatamente después de los elementos de la izquierda. No se toma en cuenta el contenido tipo texto.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>
  Selector sel1 + sel2
 </title>
 <style>
  /* Selecciona todos los
   *  strong
   * inmediatamente después de
   *  em */
  em+strong {
   background-coloryellow;
  }
 </style>
</head>
<body>
 <h1>
  Selector
  <em>sel1</em>
  <strong>+</strong>
  <em>sel2</em>
 </h1>
 <p>
  <em>Este</em>
  <strong>ejercicio</strong>
  está
  <em>muy</em>
  divertido
  <strong>ggg</strong>
  <em>jajaja</em>
  <!-- subíndice -->
  <sub>jejeje</sub>
  <strong>jijiji</strong>
  🤣🤣🤣.
 </p>
</body>
</html>

G. El selector sel1 ~ sel2

  • Seleciona los elementos que cumplan con el selector de la derecha y que sean hermanos después de los elementos de la izquierda, aunque no aparezcan juntos.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>
  Selector sel1 ~ sel2
 </title>
 <style>
  /* Selecciona todos los
   *  strong
   * hermanos después de
   *  em */
  em~strong {
   background-coloryellow;
  }
 </style>
</head>
<body>
 <h1>
  Selector
  <em>sel1</em>
  <strong>~</strong>
  <em>sel2</em>
 </h1>
 <p>
  <em>Este</em>
  <strong>ejercicio</strong>
  está
  <em>muy</em>
  divertido
  <strong>ggg</strong>
  <em>jajaja</em>
  <!-- superíndice -->
  <sup>jejeje</sup>
  <strong>jijiji</strong>
  🤣🤣🤣.
 </p>
</body>
</html>

H. La lista de selectores sel1 , sel2

  • Seleciona los elementos que cumplan con cualquiera de los selectores que aparecen separados por coma (,).

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>
  Selector sel1 , sel2
 </title>
 <style>
  /* Selecciona todos los
   *  h1, div y nav */
  h1,
  div,
  nav {
   background-coloryellow;
  }
 </style>
</head>
<body>
 <h1>Selector sel1 , sel2</h1>
 <p>Hola.</p>
 <nav>Navegación.</nav>
 <div>Adios.</div>
</body>
</html>

I. La pseudoclase :active

  • Seleciona los elementos que estén activos; por ejemplo al hacerles clic.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Selector :active</title>
 <style>
  :active {
   colorblue;
  }

  span:active {
   background-coloryellow;
  }
 </style>
</head>
<body>
 <h1>Selector :active</h1>
 <p><button>Haz Click</button></p>
 <p><span>Haz Click</span></p>
</body>
</html>

J. La pseudoclase :focus

  • Seleciona al elemento que en el momento actual reciba el control del teclado, estado que también se conoce como foco.

  • En cualquier momento, solo un componente gráfico tiene el foco.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width,
       initial-scale=1.0">
 <title>Selector :focus</title>
 <style>
  :focus {
   colorred;
  }

  input:focus {
   background-coloryellow;
  }

  textarea,
  input {
   displayblock;
  }
 </style>
</head>
<body>
 <h1>Selector :focus</h1>
 <p>
  <label>
   Nombre
   <input>
  </label>
 </p>
 <p>
  <label>
   Relato
   <textarea></textarea>
  </label>
 </p>
 <p>
  <span>Intenta teclear</span>
 </p>
</body>
</html>

K. Resumen

  • En esta lección se revisaron los siguientes selectores:

    • El selector *.

    • El selector #identificador.

    • El selector .clase.

    • El selector sel1 > sel2.

    • El selector sel1 sel2.

    • El selector sel1 + sel2.

    • El selector sel1 ~ sel2.

    • La lista de selectores sel1 , sel2.

    • La pseudoclase :active.

    • La pseudoclase :focus.

10. Elementos Multimedia

Versión para imprimir.

En esta lección se presentan algunos elementos para el manejo de multimedia.

A. Imágenes

  • Hay varios tipos de elementos especializados en mostrar imágenes.

El elemento img

  • Es un elemento de fraseo que muestra una imagen.

  • Puede tener los siguientes atributos:

    src

    URL del recurso.

    alt

    Texto que se muestra cuando no se puede descargar la imagen.

El elemento figure

  • Es un elemento de agrupamiento específicamente diseñado para mostrar imágenes.

El elemento figcaption

  • Es un elemento de agrupamiento específicamente diseñado para mostrar el texto que describe el contenido de un figure.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Imágenes</title>
</head>
<body>
 <h1>Imágenes</h1>
 <style>
  img {
   max-width100%
  }
 </style>
 <figure>
  <img alt="Un gatito"
    src="https://media.giphy.com/media/MDJ9IbxxvDUQM/giphy.gif">
  <figcaption>Gatito.</figcaption>
 </figure>
 <footer>
  <p>
   Imágen de
   <a href="https://giphy.com"
     target="_blank">
    Giphy</a>.
  </p>
 </footer>
</body>
</html>

Solo para los más rudos

B. Audio y Video

  • Respeta las licencias de uso del contenido que coloques en tu sitio.

  • Los 2 elementos se pueden usar para reproducir tanto audio como video. La principal diferencia es que el elemento audio no tiene espacio para desplegar contenido visual (como video o subtítulos), mientras que el elemento video si lo tiene.

Atributos Comunes

  • Los elementos multimedia audio y video tienen los siguientes atributos en común:

    src

    La URL del recurso de audio o video a desplegar. Si está presente, debe contener una URL no vacía. Puede rodearse con espacios.

    crossorigin

    Especifica el valor CORS (Cross-origin resource sharing), que puede ser:

    • anonymous
    • use-credentials
    preload

    Puede tener los siguientes valores:

    none

    El recurso no se descarga antes de reproducirse, pues no se espera que el usuario necesite el recurso, o el servidor espera minimizar tráfico innecesario. No se proporciona ningún indicio sobre la agresividad para descargar el recurso una vez que se empieza a reproducir.

    metadata

    Descargar solamente los metadatos del recurso (dimensiones, lista de títulos, duración, etc.) y aún unos pocos cuadros del inicio. Una vez iniciada la reproducción, los datos se descargan a la velocidad más baja que garantice una reproducción consistente.

    auto

    El usuario puede descargar el recurso agresivamente sin riesgo para el servidor, incluyendo la descarga total antes de reproducirse.

    autoplay

    Es un atributo booleano. Cuando está presente, se inicia la reproducción del recurso tan pronto como se pueda, sin detenerse. Se recomienda no usar esta característica y permitir al usuario iniciar la reproducción explícitamente.

    loop

    Es un atributo booleano. Si está presente, indica que cuando la reproducción del recurso termine, debe reiniciar.

    muted

    Es un atributo booleano. Su presencia silencia la salida de audio, potencialmente contraviniendo las preferencias del usuario.

    controls

    Es un atributo booleano. Cuando se especifica, indica que se deben mostrar los controles del elemento.

C. El elemento audio

  • Permite manejar una transmisión de audio o video.

  • Aunque este elemento puede llevar contenido, por ejemplo texto, este no se muestra al usuario; es para desplegarse en navegadores que no soportan el elemento audio, para poder probar con plugins o para indicar como acceder al contenido.

  • Si el contenido incluye subtítulos o lenguaje de señas, es mejor usar el elemento video.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Audio</title>
</head>
<body>
 <h1>Audio</h1>
 <p>
  <audio controls
    src="https://www.royaltyfreemusicclips.com/pir/libs/media/1234_Rock_it.wav">
   Tu navegador no soporta audio.
  </audio>
 </p>
 <footer>
  <p>
   Música gratuita libre de
   regalías por
   <a target="_blank"
     href="https://www.royaltyfreemusicclips.com">
    Royalty Free Music Clips</a>.
  </p>
 </footer>
</body>
</html>

Solo para los más rudos

D. El elemento video

  • Se usa para desplegar sonidos, videos o películas.

  • Aunque este elemento puede llevar contenido, por ejemplo texto, este no se muestra al usuario; es para desplegarse en navegadores que no soportan el elemento video, para poder probar con plugins o indicar como acceder al contenido.

  • Para que tu video se despliegue en el navegador Safari para las computadoras Apple (iPad, iPhone, Mac), tu servidor web debe soportar byte-range request. No todos los servidores soportan este tipo de solicitudes.

  • Una opción es usar Giphy que en formato de video es más rápido y eficiente que en el formato GIF. Al seleccionar una imagen, haz clic en Media y copia la URL del formato MP4.

Atributos adicionales

poster

Proporciona la URL de una imagen que se muestra mientras no se haya cargado ningún byte del video.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Video</title>
 <style>
  video {
   max-width100%
  }
 </style>
</head>
<body>
 <h1>Video</h1>
 <figure>
  <video autoplay loop
    src="https://media.giphy.com/media/1W62t8wP8m1iM/giphy.mp4">
   Tu navegador no soporta video.
  </video>
 </figure>
 <footer>
  <p>
   Video de
   <a href="https://giphy.com"
     target="_blank">
    Giphy</a>.
  </p>
 </footer>
</body>
</html>

Solo para los más rudos

E. Imagen de fondo

Salida.

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport"
      content="width=device-width,
       initial-scale=1.0">
    <title>Fondo</title>
    <style>
      html {
        /* Como el fondo es
         * oscuro, se escoje un
         * color de letra que no
         * se pierda. */
        colorwhite;
        /* URL de la imagen de
         * fondo. Es este caso
         * está hospedada en
         * "giphy.com". */
        background-image:
          url(https://media.giphy.com/media/3oKIPhf02cXU9W4Le0/giphy.gif);
        /* La imagen de fondo no
         * se repite en caso de
         * que sea más pequeña que
         * el elemento en que se
         * coloca. En este caso
         * html es la ventana. */
        background-repeatno-repeat;
        /* La imagen de fondo se
         * muestra centrada
         * horizontalmente. */
        background-position-x:
          center;
        /* La imagen de fondo se
         * muestra centrada
         * verticalmente. */
        background-position-y:
          center;
        /* La imagen de fondo se
         * muestra fija y no se
         * desplaza. */
        background-attachment:
          fixed;
        /* Distintas propiedades
         * para distintos
         * navegadores indicando
         * que la imagen de fondo
         * tiene un tamaño que
         * cubre toda la ventana.
         */
        -webkit-background-sizecover;
        -moz-background-sizecover;
        -o-background-sizecover;
        background-sizecover;
      }

      /* Estilo para las anclas o
       * hipervínculos. */
      a {
        /* Como el fondo es
         * oscuro, se escoje un
         * color de letra que no
         * se pierda y se distinga
         * del resto del texto. */
        coloryellow;
      }
    </style>
  </head>
  <body>
    <h1>Fondo</h1>
    <p>
      Este ejemplo te muestra como
      poner fondo a una página.
    </p>
    <footer>
      <p>
        &copy; 2022
        Gilberto Pacheco Gallegos.
      </p>
      <p>
        Imagen de
        <!--
          Ancla o hipervínculo a
          un sitio. El contenido
          es el texto que se
          muestra subrayado y al
          hacer clic en el
          hipervínculo se abre la
          URL indicada en el
          atributo href.
          
          href="https://giphy.com"
            La URL que abre este
            hipervínculo es
              https://giphy.com
        -->
        <a href="https://giphy.com">
          https://giphy.com</a>.
      </p>
    </footer>
  </body>
</html>

F. Resumen

  • En esta lección se revisaron los siguientes elementos:

    • Elementos para mostrar imágenes.

    • audio.

    • video.

  • También se revisó cómo poner una imagen de fondo.

11. Formularios

Versión para imprimir.

A. Formulario simple

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Saludo</title>
</head>

<body>
 <!--
  form
   Captura los datos para un
   cálculo.
  action="javascript:calcula()"
   Al activar la forma, se ejecuta
   la función
    calcula()
   de la etiqueta
    <script>
   que aparece más abajo. -->
 <form
   action="javascript:calcula()">
  <h1>Saludo</h1>
  <!--
   Los elementos de captura se
   pueden colocan cada uno en un
    <p> -->
  <p>
   <!--
    label
     Pone el rótulo
      Nombre
     que aparece más abajo, al
     elemento
      input
     que también aparece más abajo.
   -->
   <label>
    Nombre
    <!--
     input
      Campo de captura. Activa la
      forma al teclear
       «intro»
      cuando tiene el cursor.
     type="text"
      Captura texto
     id="inNombre"
      Identificador del campo de
      captura. Se puede usar desde
      el elemento
       <script>
      más abajo.
     required
      Este campo no se puede quedar
      en blanco. -->
    <input type="text"
      id="inNombre" required>
   </label>
  </p>
  <p>
   <!--
    button
     Activa la forma al hacerle
     click o presionado la tecla
     espacio cuando tiene el
     tabulador. -->
   <button>Calcular</button>
  </p>
 </form>
 <script>
  /**
   * Función que realiza el cálculo
   * cuando se activa la forma.
   */
  function calcula() {
   /* Recupera el texto capturado
    * en "inNombre" y lo asigna
    * a la constante "nombre". */
   const nombre = inNombre.value
   const saludo = saluda(nombre)
   /* Despliega el saludo en un
    * cuadro de diálogo. */
   alert(saludo);
  }

  /**
   * Función que realiza la lógica
   * del cálculo.
   * @param {string} nombre
   */
  function saluda(nombre) {
   return `Hola ${nombre}.`
  }
 </script>
</body>

</html>

B. El elemento form

  • Representa un hiperenlace.

  • El atributo action es el enlace a una URL para procesar su contenido. Puede indicar también procesamiento local con el JavaScript de la página.

  • Puede manipularse por medio de una colección de elementos asociados.

  • Algunos de los elementos asociados pueden representar valores editables que se pueden enviar para su procesamiento en un servidor o localmente.

  • El atributo name de la forma, representa el nombre único de la forma dentro de la colección de formas dentro de la página.

  • Las formas pueden tener uno o más elementos asociados de tipo <button type="submit"></button>.

  • Hay varias maneras de activar la forma:

    • Haciendo clic en un elemento <button type="submit"></button> asociado con la forma.

    • Usando el tabulador hasta llegar a un elemento <button type="submit"></button> asociado con la forma y oprimir la tecla ESPACIO.

    • Posicionarse en alguno de los campos de captura y oprimir la tecla ENTER.

Solo para los más rudos

C. Atributos comunes

  • Los siguientes atributos son comunes en los elementos asociados con una forma.

    value
    • Propiedad de JavaScript para asignar o recuperar el valor de captura.

    • Para textarea, select y controles de texto del elemento input.

    • Se puede usar en HTML para controles de texto del elemento input.

    name
    • Nombre único del elemento (y sus valores asociados) dentro de la forma.

    disabled
    • Atributo booleano. Cuando está presente indica que el elemento está deshabilitado y no responde a la interacción del usuario.

    maxlength
    • Para textarea y controles de texto del elemento input.

    • Es el número máximo de caracteres que el usuario puede introducir.

    minlength
    • Para textarea y controles de texto del elemento input.

    • Es el número mínimo de caracteres que el usuario puede introducir para que la captura sea válida.

    required
    • Atributo booleano. Cuando está presente indica que el valor de captura del elemento no puede estar vacío.

D. El elemento label

  • Representa un rótulo o etiqueta asociado a un control de una forma.

  • El contenido del elemento es el rótulo.

  • Se puede asignar a su atributo for el identificador del elemento con que se desea asociar la etiqueta.

  • También se puede hacer que el elemento label tenga como hijo al control para que queden asociados.

Solo para los más rudos

E. El elemento button

  • Representa un botón cuya superficie muestra el contenido del elemento.

  • El contenido del elemento es el rótulo.

  • El atributo type controla el comportamiento del botón al ser activado. Sus valores posibles son:

    submit
    • Cuando el botón se activa, el contenido de la forma se envía.

    • Es el valor por omisión.

    reset
    • Cuando el botón se activa, el contenido de la forma regresa a su estado inicial.

    button
    • Cuando el botón se activa, no tiene un comportamiento definido, pero puede configurar por medio de un script o con el atributo onclick.

Solo para los más rudos

F. El elemento input

  • Puede desplegar una gran cantidad de controles según el valor de atributo type.

  • Los campos con formato se validan antes de realizar submit.

  • Los valores más usados para type son:

    hidden
    • Campo invisible cuyo no puede se examinado o manipulado por el usuario.

    text
    • Manipula texto plano.

    search
    • Usa texto para búsquedas. Se despliega con la apariencia preferida por la plataforma donde se ejecuta.

    tel
    • Texto que representa un número telefónico válido.

    url
    • Texto que representa una URL válida.

    email
    • Texto que representa un email válido.

    password
    • Texto que representa una contraseña y por lo mismo no se muestra.

    number
    • Maneja números.

    range
    • Maneja un rango de números.

Otros atributos

valueAsNumber
  • Propiedad de JavaScript para asignar o recuperar el valor numérico de captura.

  • Para controles numéricos del elemento input.

  • Devuelve un número.

  • Si el texto es una cadena vacía o no representa un número, el valor devuelto es NaN (o sea que no es un número).

pattern
  • Para los tipos que manejan texto.

  • Expresión regular para validar el contenido. Abarca desde el inicio hasta el final del texto.

min
  • Para controles numéricos y de fecha.

  • Valor mínimo que se puede capturar.

max
  • Para controles numéricos y de fecha.

  • Valor máximo que se puede capturar.

step
  • Para controles numéricos y de fecha.

  • Granularidad o separación entre los valores que se pueden capturar. Por ejemplo, step=0.1 indica que los valores pueden ser 0, 0.1, 0.2, 0.3, etcétera. Aplica también para fechas.

  • El valor por omisión para controles numéricos es 1.

Solo para los más rudos

G. El elemento output

  • Muestra el resultado de un cálculo.

  • El contenido del elemento es el valor que muestra.

  • El valor mostrado puede consultar o cambiar desde JavaScript con la propiedad value.

Solo para los más rudos

H. División

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>División</title>
</head>

<body>
 <form
   action="javascript:procesa()">
  <h1>División</h1>
  <p>
   <label>
    a
    <input id="inA"
      type="number"
      step="0.1"
      required>
   </label>
  </p>
  <p>
   <label>
    b
    <input id="inB"
      type="number"
      step="0.1"
      required
      oninput="validaB()">
   </label>
  </p>
  <p>
   <button>Dividir</button>
  </p>
 </form>
 <script>
  const NO_0 = "No puede ser 0"

  function validaB() {
   const b = inB.valueAsNumber
   /* Debe cumplirse que b
    * sea un número diferente
    * de 0. */
   if (isNaN(b) || b !== 0) {
    inB.setCustomValidity("")
   } else {
    inB.setCustomValidity(NO_0)
   }
  }

  function procesa() {
   const a = inA.valueAsNumber
   const b = inB.valueAsNumber
   const resultado = divide(a, b)
   alert(
    `${a} / ${b} = ${resultado}`)
  }

  /**
   * @param {number} a
   * @param {number} b
   */
  function divide(a, b) {
   return a / b
  }
 </script>
</body>

</html>

I. Formulario numérico de 2 botones

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>
  Formulario con 2 botones
 </title>
</head>

<body>
 <form
   action=javascript:procSuma()>
  <h1>
   Formulario con 2 botones
  </h1>
  <p>
   <label>
    a
    <input id=inA type=number
      required min="0.1" max="100"
      step="0.1">
   </label>
  </p>
  <p>
   <label>
    b
    <input id=inB type=number
      required min="0.1" max="100"
      step="0.1">
   </label>
  </p>
  <p>
   <button>Sumar</button>
   <button formaction="javascript:
     procResta()">
    Restar
   </button>
  </p>
 </form>
 <script>
  function procSuma() {
   const a = inA.valueAsNumber
   const b = inB.valueAsNumber
   const resultado = suma(a, b)
   alert(
    `${a} + ${b} = ${resultado}`)
  }

  function procResta() {
   const a = inA.valueAsNumber
   const b = inB.valueAsNumber
   const resultado = resta(a, b)
   alert(
    `${a} - ${b} = ${resultado}`)
  }

  function suma(a, b) {
   return a + b
  }

  function resta(a, b) {
   return a - b
  }
 </script>
</body>

</html>

J. Recomendaciones

  • El siguiente orograma usa el tipo de elemento select.

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Recomendaciones</title>
</head>

<body>
 <form
   action="javascript:procesa()">
  <h1>Recomendaciones</h1>
  <p>
   <label>
    Género
    <select id="inGenero" required>
     <option value="">
      -- Selecciona --
     </option>
     <option value="pop">
      Pop
     </option>
     <option value="reg">
      Reguetón
     </option>
    </select>
   </label>
  </p>
  <p>
   <button>Recomendar</button>
  </p>
 </form>
 <script>
  function procesa() {
   const genero = inGenero.value
   const resultado =
    recomienda(genero)
   alert(resultado)
  }

  /** @param {string} genero */
  function recomienda(genero) {
   if (genero === "pop") {
    return "Para el pop te " +
     "recomiendo a Dua Lipa."
   } else if (genero === "reg") {
    return "Para el reguetón te " +
     "recomiendo a Bad Bunny."
   }
  }
 </script>
</body>

</html>

Solo para los más rudos

K. Adivina

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Adivina</title>
 <style>
  html {
   font-family: sans-serif;
   text-align: center;
  }

  img {
   max-height: 40vh;
   max-width: 100%;
  }
 </style>
</head>

<body>
 <h1>Adivina</h1>
 <figure>
  <img src="https://media.giphy.com/media/JKNn9A98JBVlu/giphy.gif"
    alt="Imagen de un animal">
  <figcaption>
   ¿Qúe animal es este?
  </figcaption>
 </figure>
 <p>
  <button onclick="rana()">
   Una Rana
  </button>
  <button onclick="oso()">
   Un Oso
  </button>
 </p>
 <script>
  function rana() {
   alert(
    "Claro que no es una rana.")
  }

  function oso() {
   alert("Claro que si es un oso.")
  }
 </script>
</body>

</html>

L. Encuesta

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>¿Cuál te gusta más?</title>
 <style>
  html {
   font-family: sans-serif;
  }

  body {
   display: grid;
   gap: 0.5rem;
   margin: 0;
   padding: 0.5rem;
   max-height: 100vh;
   overflow: hidden;
   grid-template-columns:
    1fr 1fr 1fr 1fr;
    grid-template-areas:
    "h1 h1 h1 h1"
    "outGatito btnGatito outPerrito btnPerrito"
    "imgGatito imgGatito imgPerrito imgPerrito";
  }

  h1 {
   grid-area: h1;
   text-align: center;
  }

  #outGatito {
   grid-area: outGatito;
   justify-self: center;
  }

  #btnGatito {
   grid-area: btnGatito;
  }

  #imgGatito {
   grid-area: imgGatito;
   width: 100%;
  }

  #outPerrito {
   grid-area: outPerrito;
   justify-self: center;
  }

  #btnPerrito {
   grid-area: btnPerrito;
  }

  #imgPerrito {
   grid-area: imgPerrito;
   width: 100%;
  }
 </style>
</head>

<body>
 <h1>¿Cuál te gusta más?</h1>
 <output id="outGatito">
  0 votos
 </output>
 <button id="btnGatito"
   onclick="gatito()">
  Vota
 </button>
 <img id="imgGatito" alt="Gatito"
   src="https://media.giphy.com/media/uWYjSbkIE2XIMIc7gh/giphy.gif">
 <output id=outPerrito>
  0 votos
 </output>
 <button id="btnPerrito"
   onclick=perrito()>
  Vota
 </button>
 <img id="imgPerrito"
   alt="Perrito"
   src="https://media.giphy.com/media/rXzOY4RpSA0Ug/giphy.gif">
 <script>
  let votosGatito = 0
  let votosPerrito = 0

  function gatito() {
   votosGatito++
   outGatito.value =
    `${votosGatito} votos`
  }

  function perrito() {
   votosPerrito++
   outPerrito.value =
    `${votosPerrito} votos`
  }
 </script>
</body>

</html>

M. Recomienda

Salida

Ábrelo en otra pestaña.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="utf-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Recomienda</title>
 <style>
  html {
   font-family: sans-serif;
  }

  body {
   display: grid;
   gap: 0.5rem;
   margin: 0;
   padding: 0.5rem;
   max-height: 100vh;
   grid-template-columns:
    8rem 2fr;
   grid-template-areas:
    "h1 h1"
    "ul section";
  }

  h1 {
   grid-area: h1;
   text-align: center;
  }

  ul {
   grid-area: ul;
  }

  section {
   grid-area: section;
  }

  figure {
   display: none;
   flex: 1;
   margin: 0;
   width: 100%;
  }

  figure:target {
   display: block;
  }

  img {
   flex: 1;
   width: 100%;
  }
 </style>
</head>

<body>
 <h1>Recomienda</h1>
 <ul>
  <li>
   <p>
    <a href="#pop">Pop</a>
   </p>
  </li>
  <li>
   <p>
    <a href="#reg">Reguetón</a>
   </p>
  </li>
 </ul>
 <section>
  <figure id="pop">
   <figcaption>
    Para el pop te recomiendo a
    Dua Lipa.
   </figcaption>
   <img alt="Gif de Dua Lipa"
     src="https://media.giphy.com/media/3o7WIQin38ZjlwiKOs/giphy.gif">
  </figure>
  <figure id="reg">
   <figcaption>
    Para el reguetón te recomiendo
    a Bad Bunny.
   </figcaption>
   <img alt="Gif de Bad Bunny"
     src="https://media.giphy.com/media/kfcsiSjQUyMvEZ1khq/giphy.gif">
  </figure>
 </section>
</body>

</html>

N. Resumen

  • En esta lección se revisaron los elementos principales para elaborar formularios y se presentaron algunos ejemplos.

12. Custom elements

Versión para imprimir.

En esta lección se presentan los custom elements.

A. Custom element

  • Mecanismo para declarar elementos personalizados que incluyan apariencia y comportamiento.

  • Su tipo de elemento debe llevar al menos un guión (-).

  • Son elementos de fraseo, por lo que su display predeterminado es inline-block.

  • Siempre se pone la etiqueta de inicio y la de final.

  • Esta tecnología ya viene incluida dentro de los navegadores, pero hay otros productos que implementan componentes web, como son:

    React

    https://es.reactjs.org/

    Vue.js

    https://vuejs.org/

    Angular.js

    https://angular.io/

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Custom elements</title>
 <style>
  elemento-1 {
   color: blue;
  }

  elemento-2 {
   display: block;
   background-color: aqua;
  }
 </style>
</head>

<body>
 <h1>Custom elements</h1>
 <elemento-1>Hola</elemento-1>
 <elemento-1>
  <em>Saludos</em>
 </elemento-1>
 <elemento-2>
  Estoy de buenas 😁
 </elemento-2>
</body>

</html>

B. Los custom element en acción

  • Para definir contenido y comportamiento propio debes crear una clase que extienda HTMLElement.

  • El método connectedCallback se invoca cuando el elemento se agrega a la página y en el debe agregarse el contenido propio y el manejo de eventos.

  • Luego hay que asociar un tipo de elemento con esa clase usando la instrucción customElements.define("tipo-de-elemento", Clase).

  • Posteriormente también puedes definirle reglas de estilo.

  • En este ejemplo, el contenido HTML se añade desde una plantilla de texto. Por medio de un plugin de Visual Studio Code se colorea el texto para que puedas distinguir los elementos y sus atributos. También es posible usar archivos de extensión jsx que permiten poner directamente las etiquetas en el código, pero requieren compilar el programa para generar un archivo JavaScript, que es el que se añade al sitio web.

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Acción</title>
 <script>
  class Elemento3
   extends HTMLElement {
   connectedCallback() {
    this.innerHTML = /* html */
     `Estoy volando🚁
      <strong>
       alto
      </strong>.`
    this.addEventListener("click",
     () => this.clic())
   }
   clic() {
    alert("ouch")
   }
  }
  customElements.define(
   "elemento-3", Elemento3)
 </script>
 <style>
  elemento-3 {
   cursor: pointer;
  }
 </style>
</head>

<body>
 <h1>Acción</h1>
 <elemento-3></elemento-3>
 <p>Saludos desde la tierra.</p>
 <elemento-3></elemento-3>
</body>

</html>

C. Uso de atributos

  • Los atributos de la etiqueta HTML se recuperan con this.getAttribute(nombreDelAtributo).

  • En el caso de los atributos booleanos, sSe puede verificar si están presentes en la etiqueta HTML usando this.hasAttribute(nombreDelAtributo).

Ejemplo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Atributos</title>
 <script>
  class MiSaludo
   extends HTMLElement {
   connectedCallback() {
    const nombre =
     this.getAttribute("nombre")
    const alegre =
     this.hasAttribute("alegre")
    const icono =
     alegre ? "😄" : "🖐"
    this.innerHTML = /* html */
     `${icono}
      hola
      <strong>${nombre}</strong>.`
   }
  }
  customElements.define(
   "mi-saludo", MiSaludo)
 </script>
</head>

<body>
 <h1>Atributos</h1>
 <p>
  <mi-saludo nombre="pp">
  </mi-saludo>
 </p>
 <p>
  <mi-saludo nombre="tt" alegre>
  </mi-saludo>
 </p>
</body>

</html>

D. Resumen

  • En esta lección se revisó el uso básico de los custom element.

13. Juegos

Versión para imprimir.

En esta lección se presentan técnicas para elaborar juegos.

A. Sprites

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Sprite</title>
 <style>
  .sprite {
   position: fixed;
   font-size: 3rem;
  }
 </style>
</head>

<body>
 <h1>Sprite</h1>
 <p>
  Este ejemplo te muestra como
  colocar una figura en
  cualquier lugar de la
  ventana.
 </p>
 <output class="sprite"
   style="left: 100px;
    bottom: 150px">
  😄
 </output>
</body>

</html>

B. Desplazamiento horizontal

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>
  Animación horizontal
 </title>
 <style>
  .sprite {
   position: fixed;
   font-size: 3rem;
  }
 </style>
</head>

<body>
 <h1>Animación horizontal</h1>
 <output id="carita"
   class="sprite">
  😄
 </output>
 <script>
  const REFRESCO = 5
  const VELOCIDAD = 0.5
  let x = 0
  setInterval(avanza, REFRESCO)

  function avanza() {
   const y = innerHeight / 2
   const xMáxima = innerWidth
   carita.style =
    `left: ${x}px; bottom: ${y}px`
   x = (x + VELOCIDAD) % xMáxima
  }
 </script>
</body>

</html>

C. Recta

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Animación recta</title>
 <style>
  .sprite {
   position: fixed;
   font-size: 3rem;
  }
 </style>
</head>

<body>
 <h1>Animación recta</h1>
 <output id="carita"
   class="sprite">
  😄
 </output>
 <script>
  const X_INICIAL = 0
  const REFRESCO = 5
  const VELOCIDAD = 0.5
  let x = X_INICIAL
  setInterval(avanza, REFRESCO)

  function avanza() {
   const xFinal = innerWidth
   const yInicial = innerHeight / 2
   const yFinal = innerHeight
   const y = ((yFinal - yInicial) /
    (xFinal - X_INICIAL)) *
    (x - X_INICIAL) +
    yInicial
   carita.style =
    `left: ${x}px; bottom: ${y}px`
   x = (x + VELOCIDAD) % xFinal
  }
 </script>
</body>

</html>

D. Ondula

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Ondula</title>
 <style>
  .sprite {
   position: fixed;
   font-size: 3rem;
  }
 </style>
</head>

<body>
 <h1>Ondula</h1>
 <output id="carita"
   class="sprite">
  😄
 </output>
 <script>
  const REFRESCO = 5
  const VELOCIDAD = 0.5
  const FRECUENCIA = 0.03
  let x = 0
  setInterval(avanza, REFRESCO)

  function avanza() {
   const xMáxima = innerWidth
   const amplitud = innerHeight / 3
   const yBase = innerHeight / 2
   y = yBase +
    amplitud *
    Math.sin(FRECUENCIA * x)
   carita.style =
    `left: ${x}px; bottom: ${y}px`
   x = (x + VELOCIDAD) % xMáxima
  }
 </script>
</body>

</html>

E. Girando

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Gira</title>
 <style>
  .sprite {
   position: fixed;
   font-size: 3rem;
  }
 </style>
</head>

<body>
 <h1>Gira</h1>
 <output id="mariposa"
   class="sprite">
  🦋
 </output>
 <script>
  const REFRESCO = 120
  const VELOCIDAD = 0.3
  let angulo = 0
  setInterval(gira, REFRESCO)

  function gira() {
   const xBase = innerWidth / 2
   const amplitudX = innerWidth / 3
   const yBase = innerHeight / 2
   const amplitudY =
    innerHeight / 3
   const x = xBase +
    amplitudX * Math.cos(angulo)
   const y = yBase +
    amplitudY * Math.sin(angulo)
   mariposa.style =
    `left: ${x}px; bottom: ${y}px`
   angulo += VELOCIDAD
  }
 </script>
</body>

</html>

F. Desplazamiento con botones

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Mueve con Botones</title>
 <style>
  .sprite {
   position: fixed;
   font-size: 3rem;
  }
 </style>
</head>

<body>
 <h1>Mueve con Botones</h1>
 <p>
  <button onclick="retrocede()">
   ◀
  </button>
  <button onclick="avanza()">
   ▶
  </button>
 </p>
 <output id="carita"
   class="sprite">
  😄
 </output>
 <script>
  let yBase
  let xMenor
  let xMayor
  const VELOCIDAD = 30
  actualiza()
  let x = xMenor
  dibuja()

  function retrocede() {
   actualiza()
   if (x > xMenor) {
    x -= VELOCIDAD
   }
   dibuja()
  }

  function avanza() {
   actualiza()
   if (x < xMayor) {
    x += VELOCIDAD
   }
   dibuja()
  }

  function actualiza() {
   yBase = innerHeight / 2
   xMenor = innerWidth / 5
   xMayor = 4 * innerWidth / 5
  }

  function dibuja() {
   carita.style = `left: ${x}px;
    bottom: ${yBase}px`
  }
 </script>
</body>

</html>

G. Detecta colisiones

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Choca</title>
 <style>
  .sprite {
   position: fixed;
   font-size: 3rem;
  }
 </style>
</head>

<body>
 <h1>Choca</h1>
 <output id="abrazo"
   class="sprite"
   style="background-color:
            greenyellow;">
  🤗
 </output>
 <output id="triste"
   class="sprite"
   style="background-color:
            grey;">
  😪
 </output>
 <script>
  let x = 0
  const REFRESCO = 5
  setInterval(avanza, REFRESCO)

  function avanza() {
   const velocidad =
    innerWidth / 2000
   const x2 = innerWidth
   const y = innerHeight / 2
   triste.style.left =
    `${innerWidth / 2}px`
   triste.style.bottom = `${y}px`
   abrazo.style.left = `${x}px`
   abrazo.style.bottom = `${y}px`
   if (!seTocan(abrazo, triste)) {
    x = (x + velocidad) % x2
   }
  }

  /**
   * Devuelve true si 2
   * elementos se tocan.
   * @param {HTMLElement} e1
   * @param {HTMLElement} e2
   * @returns {boolean} true
   *  si los elementos se
   *  tocan.
   */
  function seTocan(e1, e2) {
   const rE1 =
    e1.getBoundingClientRect()
   const rE2 =
    e2.getBoundingClientRect()
   return (rE1.right >= rE2.left
    && rE1.left <= rE2.right
    && rE1.top <= rE2.bottom
    && rE1.bottom >= rE2.top)
  }
 </script>
</body>

</html>

H. Haz algo si chocamos

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Sonrie</title>
 <style>
  .sprite {
   position: fixed;
   font-size: 3rem;
  }
 </style>
</head>

<body>
 <h1>Sonrie</h1>
 <output id="abrazo"
   class="sprite"
   style="background-color:
            greenyellow;">
  🤗
 </output>
 <output id="triste"
   class="sprite"
   style="background-color:
            grey;">
  😪
 </output>
 <script>
  let x = 0
  const REFRESCO = 5
  let intervalo =
   setInterval(avanza, REFRESCO)

  function avanza() {
   const velocidad =
    innerWidth / 2000
   const x2 = innerWidth
   const y = innerHeight / 2
   triste.style.left =
    `${innerWidth / 2}px`
   triste.style.bottom = `${y}px`
   abrazo.style.left = `${x}px`
   abrazo.style.bottom = `${y}px`
   if (seTocan(abrazo, triste)) {
    triste.value = "😊";
    triste.style.
     backgroundColor = "pink";
    clearInterval(intervalo);
   } else {
    x = (x + velocidad) % x2
   }
  }

  /**
   * Devuelve true si 2
   * elementos se tocan.
   * @param {HTMLElement} e1
   * @param {HTMLElement} e2
   * @returns {boolean} true
   *  si los elementos se
   *  tocan.
   */
  function seTocan(e1, e2) {
   const rE1 =
    e1.getBoundingClientRect()
   const rE2 =
    e2.getBoundingClientRect()
   return (rE1.right >= rE2.left
    && rE1.left <= rE2.right
    && rE1.top <= rE2.bottom
    && rE1.bottom >= rE2.top)
  }
 </script>
</body>

</html>

I. Muévete al azar

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Sonrie</title>
 <style>
  .sprite {
   position: fixed;
   font-size: 3rem;
  }
 </style>
</head>

<body>
 <h1>Sonrie</h1>
 <output id="abrazo"
   class="sprite"
   style="background-color:
            greenyellow;">
  🤗
 </output>
 <output id="triste"
   class="sprite"
   style="background-color:
            grey;">
  😪
 </output>
 <script>
  let x = 0
  const REFRESCO = 5
  let intervalo =
   setInterval(avanza, REFRESCO)

  function avanza() {
   const velocidad =
    innerWidth / 2000
   const x2 = innerWidth
   const y = innerHeight / 2
   triste.style.left =
    `${innerWidth / 2}px`
   triste.style.bottom = `${y}px`
   abrazo.style.left = `${x}px`
   abrazo.style.bottom = `${y}px`
   if (seTocan(abrazo, triste)) {
    triste.value = "😊";
    triste.style.
     backgroundColor = "pink";
    clearInterval(intervalo);
   } else {
    x = (x + velocidad) % x2
   }
  }

  /**
   * Devuelve true si 2
   * elementos se tocan.
   * @param {HTMLElement} e1
   * @param {HTMLElement} e2
   * @returns {boolean} true
   *  si los elementos se
   *  tocan.
   */
  function seTocan(e1, e2) {
   const rE1 =
    e1.getBoundingClientRect()
   const rE2 =
    e2.getBoundingClientRect()
   return (rE1.right >= rE2.left
    && rE1.left <= rE2.right
    && rE1.top <= rE2.bottom
    && rE1.bottom >= rE2.top)
  }
 </script>
</body>

</html>

J. Usa custom element

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Custom Elements</title>
 <style>
  figura-web {
   position: fixed;
   font-size: 60px;
  }
 </style>
 <script>
  class FiguraWeb
   extends HTMLElement {
   connectedCallback() {
    this.x = 0
    const attrY =
     this.getAttribute("y")
    const attrVel =
     this.getAttribute("velocidad")
    this.y = parseInt(attrY, 10)
    this.velocidad =
     parseInt(attrVel, 10)
   }
   muevete() {
    this.style.right =
     `${this.x}px`
    this.style.top = `${this.y}px`
    this.x =
     (this.x + this.velocidad) %
     innerWidth
   }
  }
  customElements.define(
   "figura-web", FiguraWeb)
 </script>
</head>

<body>
 <h1>Custom Elements</h1>
 <figura-web id="fantasma"
   y="0" velocidad="20">
  👻
 </figura-web>
 <figura-web id="sonrisa"
   y="100" velocidad="10">
  😁
 </figura-web>
 <script>
  setInterval(anima, 120)

  function anima() {
   fantasma.muevete()
   sonrisa.muevete()
  }
 </script>
</body>

</html>

K. Asociaciones

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Asociaciones</title>
 <script>
  /**
   * Devuelve un número
   * aleatorio entre el valor
   * menor y el valor mayor.
   * @param {number} menor el
   *  menor valor que se puede
   *  generar
   * @param {number} mayor el
   *  mayor valor que se puede
   *  generar
   * @returns {number} un
   *  número aleatorio entre
   *  menor y mayor.
   */
  function
   aleatorio(menor, mayor) {
   /* Math.floor(x): elimina
    *  los decimales.
    * Math.random(): genera
    *  un número aleatorio
    *  >= 0 y < 1. */
   return menor +
    Math.floor(
     Math.random() *
     (mayor - menor + 1))
  }

  class PerroWeb
   extends HTMLElement {
   connectedCallback() {
    this.x = 0
    this.y = 0
    this.innerHTML = "🐕"
    this.style.position = "fixed"
    this.style.fontSize = "2rem"
    this.style.right =
     `${this.x}px`
    this.style.bottom =
     `${this.y}px`
   }

   muevete() {
    this.x = (this.x + 30) %
     innerWidth
    this.style.right =
     `${this.x}px`
   }
  }
  customElements.define(
   "perro-web", PerroWeb)

  class AguilaWeb
   extends HTMLElement {
   connectedCallback() {
    this.x = aleatorio(0,
     Math.floor(innerWidth))
    this.y = aleatorio(0,
     Math.floor(innerHeight))
    this.innerHTML = "🦅"
    this.style.position = "fixed"
    this.style.fontSize = "2.5rem"
    this.style.left = `${this.x}px`
    this.style.top = `${this.y}px`
   }

   muevete() {
    this.y = (this.y + 10) %
     innerHeight
    this.style.top = `${this.y}px`
   }
  }
  customElements.define(
   "aguila-web", AguilaWeb)

  class ControladorWeb
   extends HTMLElement {
   connectedCallback() {
    this.muevete =
     this.muevete.bind(this)
    this.innerHTML = /* html */
     `<button onclick="this.
        parentElement.muevete()">
       Mueve
      </button>`
    this.perro = new PerroWeb()
    this.aguilas = [
     new AguilaWeb(),
     new AguilaWeb()]
    this.append(this.perro)
    for (const a of this.aguilas) {
     this.append(a)
    }
   }

   muevete() {
    this.perro.muevete()
    for (let a of this.aguilas) {
     a.muevete()
    }
   }
  }
  customElements.define(
   "controlador-web",
   ControladorWeb)
 </script>
</head>

<body>
 <h1>Asociaciones</h1>
 <controlador-web>
 </controlador-web>
</body>

</html>

L. Polimorfismo

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Polimorfismo</title>
 <script>
  function
   aleatorio(menor, mayor) {
   return menor +
    Math.floor(
     Math.random() *
     (mayor - menor + 1))
  }

  /** @interface */
  class SeMueve {
   muevete() {
    throw new Error("intf")
   }
  }

  /** @implements {SeMueve} */
  class PerroWeb
   extends HTMLElement {
   connectedCallback() {
    this.x = 0
    this.y = 0
    this.innerHTML = "🐕"
    this.style.position = "fixed"
    this.style.fontSize = "2rem"
    this.style.right =
     `${this.x}px`
    this.style.bottom =
     `${this.y}px`
   }

   muevete() {
    this.x = (this.x + 30) %
     window.innerWidth
    this.style.right =
     `${this.x}px`
   }
  }
  customElements.define(
   "perro-web", PerroWeb)

  /** @implements {SeMueve} */
  class AguilaWeb
   extends HTMLElement {
   connectedCallback() {
    this.x = aleatorio(0,
     Math.floor(innerWidth))
    this.y = aleatorio(0,
     Math.floor(innerHeight))
    this.innerHTML = "🦅"
    this.style.position = "fixed"
    this.style.fontSize = "2.5rem"
    this.style.left = `${this.x}px`
    this.style.top = `${this.y}px`
   }

   muevete() {
    this.y = (this.y + 10) %
     window.innerHeight
    this.style.top = `${this.y}px`
   }
  }
  customElements.define(
   "aguila-web", AguilaWeb)
 </script>
</head>

<body>
 <h1>Polimorfismo</h1>
 <p>
  <button onclick="mueve()">
   Mueve
  </button>
 </p>
 <script>
  const figuras = [
   new AguilaWeb(),
   new PerroWeb(),
   new AguilaWeb()]
  for (let f of figuras) {
   document.body.append(f)
  }
  function mueve() {
   for (var f of figuras) {
    f.muevete()
   }
  }
 </script>
</body>

</html>

M. Jueguito 1

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html>

<head>
 <meta charset="utf-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Jueguito 1</title>
 <style>
  body {
   /* Rompe el flujo normal para
    * poder hacer swipe hacia
    * abajo. */
   position: fixed;
   top: 0px;
   left: 0px;
   /* ocupa todo el espacio. */
   width: 100%;
   height: 100%;
   /* Elimina márgenes. */
   margin: 0;
   /* Evita el scroll */
   overflow: hidden;
  }

  .sprite {
   position: fixed;
  }
 </style>
 <script>
  //@ts-check
  class JugadorPaloma
   extends HTMLElement {
   connectedCallback() {
    this.classList.add("sprite")
    this.innerHTML += "🕊"
    this.style.fontSize = "60px"
    /* Coloca el elemento a la
     * mitad de la pantalla. */
    const raiz =
     document.documentElement
    /* Obtiene las coordenadas del
     * element. */
    const r =
     this.getBoundingClientRect()
    const left =
     (raiz.clientWidth - r.width) /
     2
    const top =
     (raiz.clientHeight -
      r.height) /
     2
    this.style.left = `${left}px`
    this.style.top = `${top}px`
   }

   sube() {
    const top =
     this.getBoundingClientRect().
      top -
     20
    this.style.top = `${top}px`
   }

   baja() {
    const top =
     this.getBoundingClientRect().
      top +
     20
    this.style.top = `${top}px`
   }

   izquierda() {
    const left =
     this.getBoundingClientRect().
      left -
     20
    this.style.left = `${left}px`
   }

   derecha() {
    const left =
     this.getBoundingClientRect().
      left +
     20
    this.style.left = `${left}px`
   }
  }
  customElements.define(
   "jugador-paloma", JugadorPaloma)

  class FiguraAguila
   extends HTMLElement {
   connectedCallback() {
    this.classList.add("sprite")
    this.innerHTML = "🦅"
    this.style.fontSize = "40px"
    const r =
     this.getBoundingClientRect()
    this.style.left = `${r.left}px`
    this.style.top = `${r.top}px`
    this.style.bottom = "auto"
    this.style.right = "auto"
   }

   /**
    * Mueve la figura para que se
    * acerque al jugador, usando la
    * ecuación de la recta.
    * @param {HTMLElement} jugador
    *   el jugador que es
    *   perseguido.
    */
   muevete(jugador) {
    const r =
     this.getBoundingClientRect()
    const rJ = jugador.
     getBoundingClientRect()
    const y2 = rJ.top
    const y1 = r.top
    const x2 = rJ.left
    const x1 = r.left
    const pendiente = x2 === x1 ?
     0 :
     (y2 - y1) / (x2 - x1)
    const dirección =
     x2 > x1 ? 1 : -1
    const x = x1 + dirección * 5
    const y =
     pendiente * (x - x1) + y1
    this.style.left = `${x}px`
    this.style.top = `${y}px`
   }
  }
  customElements.define(
   "figura-aguila", FiguraAguila)
 </script>
</head>

<body>
 <div>
  <jugador-paloma></jugador-paloma>
  <figura-aguila
    style="right: 0; top: 0;">
  </figura-aguila>
  <figura-aguila
    style="right: 0; bottom: 0;">
  </figura-aguila>
 </div>
 <script>
  //@ts-check
  class Juego {
   constructor() {
    /** @type {JugadorPaloma} */
    this.jugador = document.
     querySelector(
      "jugador-paloma")
    /** @type {FiguraAguila[]} */
    this.figuras = Array.from(
     document.querySelectorAll(
      "figura-aguila"))
    this.iniciaX = null
    this.iniciaY = null
    this.interval = null
    this.activo = true
   }

   inicia() {
    document.addEventListener(
     "keydown",
     evt => this.teclas(evt))
    this.interval = setInterval(
     () => this.mueveFiguras(), 60)
   }

   mueveFiguras() {
    for (const f of this.figuras) {
     f.muevete(this.jugador)
    }
   }

   /** @param {KeyboardEvent} ev*/
   teclas(ev) {
    if (this.activo) {
     switch (ev.key) {
      case "ArrowLeft":
       this.jugador.izquierda()
       break
      case "ArrowRight":
       this.jugador.derecha()
       break
      case "ArrowUp":
       this.jugador.sube()
       break
      case "ArrowDown":
       this.jugador.baja()
       break
     }
    }
   }
  }

  const juego = new Juego()
  juego.inicia()
 </script>
</body>

</html>

N. Jueguito 2

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html>

<head>
 <meta charset="utf-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Jueguito 2</title>
 <style>
  body {
   position: fixed;
   top: 0px;
   left: 0px;
   width: 100%;
   height: 100%;
   margin: 0;
   overflow: hidden;
  }

  .sprite {
   position: fixed;
  }
 </style>
 <script>
  //@ts-check
  /** @abstract */
  class Jugador
   extends HTMLElement {
   izquierda() {
    throw new Error("abstract")
   }
   derecha() {
    throw new Error("abstract")
   }
   sube() {
    throw new Error("abstract")
   }
   baja() {
    throw new Error("abstract")
   }
  }

  /** @abstract */
  class Figura
   extends HTMLElement {
   /**
    * @param {HTMLElement} jugador
    *   el jugador que persigue.
    */
   muevete(jugador) {
    throw new Error("abstract");
   }
  }

  class Juego2 {
   constructor() {
    /** @type {Jugador} */
    this.jugador = document.
     querySelector(".jugador")
    /** @type {Figura[]} */
    this.figuras = Array.from(
     document.querySelectorAll(
      ".figura"))
    this.iniciaX = null
    this.iniciaY = null
    this.interval = null
    this.activo = true
   }

   inicia() {
    document.addEventListener(
     "keydown",
     evt => this.teclas(evt))
    document.addEventListener(
     "touchstart",
     evt => this.iniciaTouch(evt))
    document.addEventListener(
     "touchmove",
     evt =>
      this.desplazaTouch(evt))
    this.interval = setInterval(
     () => this.mueveFiguras(), 60)
   }

   mueveFiguras() {
    for (const f of this.figuras) {
     f.muevete(this.jugador)
    }
    this.detectaColisiones()
   }

   detectaColisiones() {
    for (const f of this.figuras) {
     if (colisiona(
      this.jugador, f)) {
      this.termina()
      break
     }
    }
   }

   termina() {
    this.activo = false
    clearInterval(this.interval)
    alert("Jueguito 2 terminado.")
   }

   /** @param {KeyboardEvent} evt*/
   teclas(evt) {
    if (this.activo) {
     switch (evt.key) {
      case "ArrowLeft":
       this.jugador.izquierda()
       break
      case "ArrowRight":
       this.jugador.derecha()
       break
      case "ArrowUp":
       this.jugador.sube()
       break
      case "ArrowDown":
       this.jugador.baja()
       break
     }
     this.detectaColisiones()
    }
   }

   /** @param {TouchEvent} evt */
   iniciaTouch(evt) {
    if (this.activo) {
     const toqueInicial =
      evt.touches[0]
     this.iniciaX =
      toqueInicial.clientX
     this.iniciaY =
      toqueInicial.clientY
    }
   }

   /** @param {TouchEvent} evt */
   desplazaTouch(evt) {
    if (this.activo
     && this.iniciaX
     && this.iniciaY) {
     const desplazamiento =
      evt.touches[0]
     var desplazamientoX =
      desplazamiento.clientX
     var desplazamientoY =
      desplazamiento.clientY
     var difX = desplazamientoX -
      this.iniciaX
     var difY = desplazamientoY -
      this.iniciaY
     /* Checa que el movimiento no
      * sea muy corto. */
     if (Math.abs(difX)
      + Math.abs(difY)
      > 150) {
      if (Math.abs(difX)
       > Math.abs(difY)) {
       if (difX > 70) {
        this.jugador.derecha()
       } else {
        this.jugador.izquierda()
       }
      } else if (difY > 70) {
       this.jugador.baja()
      } else {
       this.jugador.sube()
      }
      this.detectaColisiones()
      // Reinicia valores.
      this.iniciaX = null;
      this.iniciaY = null;
     }
    }
   }
  }

  /**
   * @param {HTMLElement} e1
   * @param {HTMLElement} e2
   * @returns {boolean} true si los
   *    element colisionan.
   */
  function colisiona(e1, e2) {
   const rE1 =
    e1.getBoundingClientRect()
   const rE2 =
    e2.getBoundingClientRect()
   return (rE1.right >= rE2.left
    && rE1.left <= rE2.right
    && rE1.top <= rE2.bottom
    && rE1.bottom >= rE2.top)
  }

  customElements.define(
   "jugador-paloma",
   class extends Jugador {
    connectedCallback() {
     this.classList.add("sprite")
     this.classList.add("jugador")
     this.innerHTML += "🕊"
     this.style.fontSize = "60px"
     const raiz =
      document.documentElement
     const r =
      this.getBoundingClientRect()
     const left =
      (raiz.clientWidth
       - r.width) /
      2
     const top =
      (raiz.clientHeight -
       r.height) /
      2
     this.style.left = `${left}px`
     this.style.top = `${top}px`
    }

    /** @override */
    sube() {
     const top =
      this.getBoundingClientRect().
       top -
      20
     this.style.top = `${top}px`
    }

    /** @override */
    baja() {
     const top =
      this.getBoundingClientRect().
       top +
      20
     this.style.top = `${top}px`
    }

    izquierda() {
     const left =
      this.getBoundingClientRect().
       left -
      20
     this.style.left = `${left}px`
    }

    derecha() {
     const left =
      this.getBoundingClientRect().
       left +
      20
     this.style.left = `${left}px`
    }
   })

  customElements.define(
   "figura-aguila",
   class extends Figura {
    connectedCallback() {
     this.classList.add("sprite")
     this.classList.add("figura")
     this.innerHTML = "🦅"
     this.style.fontSize = "40px"
     const r =
      this.getBoundingClientRect()
     this.style.left =
      `${r.left}px`
     this.style.top = `${r.top}px`
     this.style.bottom = "auto"
     this.style.right = "auto"
    }

    /**
     * @param {HTMLElement} jugador
     *   el jugador que es
     *   perseguido.
     * @override
     */
    muevete(jugador) {
     const r =
      this.getBoundingClientRect()
     const rJ = jugador.
      getBoundingClientRect()
     const y2 = rJ.top
     const y1 = r.top
     const x2 = rJ.left
     const x1 = r.left
     const pendiente = x2 === x1 ?
      0 :
      (y2 - y1) / (x2 - x1)
     const dirección =
      x2 > x1 ? 1 : -1
     const x = x1 + dirección * 5
     const y =
      pendiente * (x - x1) + y1
     /* Evita que las figuras se
      * peguen, añadiendo un
      * movimiento aleatorio. */
     this.style.left =
      `${desvía(x)}px`
     this.style.top =
      `${desvía(y)}px`
    }
   })

  /**
   * Obtiene una desviación
   * aleatoria de 10 alrededor del
   * valor i.
   * @param {number} i valor base
   */
  function desvía(i) {
   return i + 10 -
    20 * Math.random()
  }
 </script>
</head>

<body>
 <jugador-paloma></jugador-paloma>
 <figura-aguila
   style="right: 0; top: 0;">
 </figura-aguila>
 <figura-aguila
   style="right: 0; bottom: 0;">
 </figura-aguila>
 <script>
  //@ts-check
  const juego2 = new Juego2()
  juego2.inicia()
 </script>
</body>

</html>

O. Jueguito 3

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html>

<head>
 <meta charset="utf-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Jueguito 3</title>
 <style>
  body {
   position: fixed;
   top: 0px;
   left: 0px;
   width: 100%;
   height: 100%;
   margin: 0;
   overflow: hidden;
  }

  .sprite {
   position: fixed;
  }
 </style>
 <script>
  //@ts-check
  /** @abstract */
  class Jugador
   extends HTMLElement {
   /** @param {number} velocidad */
   izquierda(velocidad) {
    throw new Error("abstract")
   }
   /** @param {number} velocidad */
   derecha(velocidad) {
    throw new Error("abstract")
   }
   /** @param {number} velocidad */
   sube(velocidad) {
    throw new Error("abstract")
   }
   /** @param {number} velocidad */
   baja(velocidad) {
    throw new Error("abstract")
   }
  }

  /** @abstract */
  class Figura
   extends HTMLElement {
   /**
    * @param {HTMLElement} jugador
    *   el jugador que es
    *   perseguido.
    */
   muevete(jugador) {
    throw new Error("abstract")
   }
  }

  /** @interface */
  class Fabrica {
   /**
    * Devuelve el único jugador,
    * por lo que se considera
    * Singleton.
    *  @returns {Jugador}
    */
   jugador() {
    throw new Error("interface")
   }
   /**
    * Devuelve un arreglo con las
    * figuras del juego.
    * @returns {Figura[]}
    */
   figuras() {
    throw new Error("interface")
   }
  }

  class Juego3 {
   /** @param {Fabrica} fabrica */
   constructor(fabrica) {
    this.jugador =
     fabrica.jugador()
    this.figuras =
     fabrica.figuras()
    this.iniciaX = null
    this.iniciaY = null
    this.interval = null
    this.activo = true
   }

   inicia() {
    document.addEventListener(
     "keydown",
     evt => this.teclas(evt))
    document.addEventListener(
     "touchstart",
     evt => this.iniciaTouch(evt))
    document.addEventListener(
     "touchmove",
     evt =>
      this.desplazaTouch(evt))
    this.interval = setInterval(
     () => this.mueveFiguras(), 60)
   }

   mueveFiguras() {
    for (const f of this.figuras) {
     f.muevete(this.jugador)
    }
    this.detectaColisiones()
   }

   detectaColisiones() {
    for (const f of this.figuras) {
     if (colisiona(
      this.jugador, f)) {
      this.termina()
      break
     }
    }
   }

   termina() {
    this.activo = false
    clearInterval(this.interval)
    this.jugador.innerHTML = "💥"
   }

   /** @param {KeyboardEvent} evt*/
   teclas(evt) {
    if (this.activo) {
     switch (evt.key) {
      case "ArrowLeft":
       this.jugador.izquierda(20)
       break
      case "ArrowRight":
       this.jugador.derecha(20)
       break
      case "ArrowUp":
       this.jugador.sube(20)
       break
      case "ArrowDown":
       this.jugador.baja(20)
       break
     }
     this.detectaColisiones()
    }
   }

   /** @param {TouchEvent} evt */
   iniciaTouch(evt) {
    if (this.activo) {
     const toqueInicial =
      evt.touches[0]
     this.iniciaX =
      toqueInicial.clientX
     this.iniciaY =
      toqueInicial.clientY
    }
   }

   /** @param {TouchEvent} evt */
   desplazaTouch(evt) {
    if (this.activo
     && this.iniciaX
     && this.iniciaY) {
     const desplazamiento =
      evt.touches[0]
     var desplazamientoX =
      desplazamiento.clientX
     var desplazamientoY =
      desplazamiento.clientY
     var difX = desplazamientoX -
      this.iniciaX
     var difY = desplazamientoY -
      this.iniciaY
     if (Math.abs(difX)
      + Math.abs(difY)
      > 150) {
      if (Math.abs(difX)
       > Math.abs(difY)) {
       if (difX > 70) {
        this.jugador.derecha(40)
       } else {
        this.jugador.izquierda(40)
       }
      } else if (difY > 70) {
       this.jugador.baja(40)
      } else {
       this.jugador.sube(40)
      }
      this.detectaColisiones()
      this.iniciaX = null
      this.iniciaY = null
     }
    }
   }
  }

  /**
   * @param {HTMLElement} e1
   * @param {HTMLElement} e2
   * @returns {boolean} true si los
   *    element colisionan.
   */
  function colisiona(e1, e2) {
   const rE1 =
    e1.getBoundingClientRect()
   const rE2 =
    e2.getBoundingClientRect()
   return (rE1.right >= rE2.left
    && rE1.left <= rE2.right
    && rE1.top <= rE2.bottom
    && rE1.bottom >= rE2.top)
  }

  customElements.define(
   "jugador-paloma",
   class extends Jugador {
    connectedCallback() {
     this.classList.add("sprite")
     this.innerHTML += "🕊"
     this.style.fontSize = "60px"
     const raiz =
      document.documentElement
     const r =
      this.getBoundingClientRect()
     const left =
      (raiz.clientWidth
       - r.width) /
      2
     const top =
      (raiz.clientHeight -
       r.height) /
      2
     this.style.left = `${left}px`
     this.style.top = `${top}px`
    }

    /**
     * @param {number} velocidad
     * @override
     */
    sube(velocidad) {
     const top =
      this.getBoundingClientRect().
       top -
      velocidad
     this.style.top = `${top}px`
    }

    /**
     * @param {number} velocidad
     * @override
     */
    baja(velocidad) {
     const top =
      this.getBoundingClientRect().
       top +
      velocidad
     this.style.top = `${top}px`
    }

    /**
     * @param {number} velocidad
     * @override
     */
    izquierda(velocidad) {
     const left =
      this.getBoundingClientRect().
       left -
      velocidad
     this.style.left = `${left}px`
    }

    /**
     * @param {number} velocidad
     * @override
     */
    derecha(velocidad) {
     const left =
      this.getBoundingClientRect().
       left +
      velocidad
     this.style.left = `${left}px`
    }
   })

  customElements.define(
   "figura-aguila",
   class extends Figura {
    connectedCallback() {
     this.classList.add("sprite")
     this.innerHTML = "🦅"
     this.style.fontSize = "40px"
     const r =
      this.getBoundingClientRect()
     this.style.left =
      `${r.left}px`
     this.style.top = `${r.top}px`
     this.style.bottom = "auto"
     this.style.right = "auto"
    }

    /**
     * @param {HTMLElement} jugador
     *   el jugador que persigue.
     * @override
     */
    muevete(jugador) {
     const r =
      this.getBoundingClientRect()
     const rJ = jugador.
      getBoundingClientRect()
     const y2 = rJ.top
     const y1 = r.top
     const x2 = rJ.left
     const x1 = r.left
     const pendiente = x2 === x1 ?
      0 :
      (y2 - y1) / (x2 - x1)
     const dirección =
      x2 > x1 ? 1 : -1
     const x = x1 + dirección * 5
     const y =
      pendiente * (x - x1) + y1
     this.style.left =
      `${desvía(x)}px`
     this.style.top =
      `${desvía(y)}px`
    }
   })

  function desvía(i) {
   return i + 10 -
    20 * Math.random()
  }
 </script>
</head>

<body>
 <jugador-paloma></jugador-paloma>
 <figura-aguila
   style="right: 0; top: 0;">
 </figura-aguila>
 <figura-aguila
   style="right: 0; bottom: 0;">
 </figura-aguila>
 <script>
  //@ts-check
  /** @implements {Fabrica} */
  class MiFabrica {
   constructor() {
    /** @type {Jugador} */
    this.jugadorSingleton =
     document.querySelector(
      "jugador-paloma");
   }
   /**
    * Devuelve el único jugador,
    * por lo que se considera
    * Singleton.
    * @returns {Jugador}
    */
   jugador() {
    return this.jugadorSingleton
   }
   /**
    * Devuelve un arreglo con las
    * figuras del juego.
    * @returns {Figura[]}
    */
   figuras() {
    return Array.from(
     document.querySelectorAll(
      "figura-aguila"))
   }
  }
  const juego =
   new Juego3(new MiFabrica())
  juego.inicia()
 </script>
</body>

</html>

P. Resumen

  • En esta lección se revisaron los elementos principales para elaborar formularios y se presentaron algunos ejemplos.

14. Adornos

Versión para imprimir.

En esta lección se presentan ejemplos de adornos en una página web.

A. Adorno horizontal

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Adorno Horizontal</title>
 <style>
  .sprite {
   position: fixed;
  }
 </style>
</head>

<body>
 <h1>Adorno Horizontal</h1>
 <script>
  const Y = 0
  const DISTANCIA = 20
  const X_MÁXIMA = innerWidth
  let x = 0
  /**
   * En esta variable se agregael
   * HTML de las figuras que forman
   * el adorno.
   */
  let inner = ""
  while (x < X_MÁXIMA) {
   /* Agrega el HTML de un emoji a
    * inner. */
   inner += /* html */
    `<div class="sprite"
       style="top: ${Y}px;
              left: ${x}px;">
      💕
     </div>`
   x += DISTANCIA
  }
  /* Agrega las figuras al HTML de
   * body. */
  document.body.innerHTML += inner
 </script>
</body>

</html>

B. Recta usando ciclos

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="utf-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Línea</title>
</head>

<body>
 <script>
  for (let x = 0; x < 200
   ; x += 20) {
   let y = 0.45 * x + 30;
   document.body.innerHTML +=
    /* html */
    `<div
       style="position: absolute;
             bottom: ${y}px;
             left: ${x}px;">
      💕
     </div>`
  }
 </script>
</body>

</html>

C. Espiral

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

<!DOCTYPE html>
<html lang="es">

<head>
 <meta charset="UTF-8">
 <meta name="viewport"
   content="width=device-width">
 <title>Adorno con Giro</title>
 <style>
  .sprite {
   position: fixed;
  }
 </style>
</head>

<body>
 <h1>Adorno con Giro</h1>
 <script>
  const INCREMENTO =
   2 * Math.PI / 21
  const X_BASE = innerWidth / 2
  const Y_BASE = innerHeight / 2
  const ANGULO_FINAL = 6 * Math.PI
  const amplitud = Math.min(
   window.innerHeight,
   window.innerWidth) /
   (3 * ANGULO_FINAL)
  let inner = ""
  for (let angulo = 0
   ; angulo < ANGULO_FINAL
   ; angulo += INCREMENTO) {
   const r = amplitud * angulo
   const x =
    X_BASE + r * Math.cos(angulo)
   const y =
    Y_BASE + r * Math.sin(angulo)
   inner += /* html */
    `<div class="sprite"
       style="bottom: ${y}px;
              left: ${x}px;">
      ⌛
     </div>`
  }
  document.body.innerHTML += inner
 </script>
</body>

</html>

D. Resumen

  • En esta lección se revisó como poner adornos a una página web.