por Gilberto Pacheco Gallegos
Este sitio presenta conceptos básicos de HTML y CSS.
A partir de la lección 11 se requiere que uses el contenido de https://gilpgijs.github.io y https://gilpgpoojs.github.io.
Puedes ver el listado de mis sitios educativos en https://gilpgcl.github.io.
Los siguientes controles te permitirán navegar por todo el contenido del sitio.
Oculta el menú de navegación.
Muestra el menú de navegación.
Regresa a la página anterior.
Avanza a la página siguiente.
En esta lección se presenta el lenguaje 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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>Ejemplo</title> |
8 | </head> |
9 | <body> |
10 | <h1>Ejemplo</h1> |
11 | <p>Hola mundo.👶</p> |
12 | </body> |
13 | </html> |
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.
1 | <!DOCTYPE html> |
El DOCTYPE de HTML5 está definido de forma muy técnica en https://html.spec.whatwg.org/multipage/.
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.
1 | <!DOCTYPE html> |
2 | <!-- |
3 | Comentario acerca de html. |
4 | --> |
5 | <html lang="es"> |
6 | <head> |
7 | <meta charset="UTF-8"><!--meta--> |
8 | </html> |
El contenido y otras partes de la página se representan con texto.
La forma de mostrar el texto se puede cambiar usando marcas.
1 | <!DOCTYPE html> |
2 | ❤Este texto es el contenido 📖 de |
3 | la página!!!! |
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.
1 | <!DOCTYPE html> |
2 | <!-- Elemento de tipo html--> |
3 | <html lang="es"> |
4 | <!-- Elemento de tipo head--> |
5 | <head> |
6 | <!-- Elemento de tipo meta--> |
7 | <meta charset="UTF-8"> |
8 | </head> |
9 | </html> |
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.
1 | <!DOCTYPE html> |
2 | <!-- |
3 | El atributo |
4 | id |
5 | No se puede repetir en el |
6 | documento y vale |
7 | raíz |
8 | |
9 | El atributo |
10 | lang |
11 | tiene el valor |
12 | es |
13 | |
14 | El atributo booleano |
15 | hidden |
16 | tiene el valor |
17 | true |
18 | --> |
19 | <html id="raíz" lang="es" hidden> |
20 | </html> |
Lleva:
tipo,
atributos (opcionalmente) y
contenido (opcionalmente), que incluye texto y más etiquetas.
Se escribe usando 2 tipos de etiquetas:
Inicia la definición del elemento.
Lleva el tipo y opcionalmente los atributos.
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.
1 | <!DOCTYPE html> |
2 | <!-- |
3 | html es un elemento con contenido. |
4 | Puede contener comentarios, otros |
5 | elementos y texto. |
6 | --> |
7 | <html lang="es"><!--Inicia html--> |
8 | <!-- |
9 | head es contenido de html. |
10 | También es elemento con contenido. |
11 | --> |
12 | <head> <!-- Inicia head --> |
13 | <!-- |
14 | meta es contenido de head. |
15 | No es un elemento con contenido. |
16 | --> |
17 | <meta charset="UTF-8"> |
18 | </head> <!-- Termina head --> |
19 | 💪Este texto es contenido de html. |
20 | </html><!-- Termina html --> |
Lleva:
tipo
atributos (opcionalmente)
Se escribe usando solo una etiqueta inicial.
El doctype determina si un elemento no lleva contenido.
1 | <!DOCTYPE html> |
2 | <!-- |
3 | meta es un tipo de elemento sin |
4 | contenido. |
5 | --> |
6 | <meta charset="UTF-8"> |
7 | <meta name="viewport" |
8 | content="width=device-width"> |
9 | <!-- |
10 | br es un tipo de elemento sin |
11 | contenido. |
12 | --> |
13 | <br> |
Un elemento es padre de todos los textos, comentarios, y elementos que formen parte de su contenido.
1 | <!DOCTYPE html> |
2 | <!-- |
3 | El elemento html es padre de los |
4 | elementos head y body. |
5 | --> |
6 | <html lang="es"> |
7 | <!-- |
8 | El elemento head es padre de los |
9 | 2 elementos meta y del title. |
10 | --> |
11 | <head> |
12 | <meta charset="UTF-8"> |
13 | <meta name="viewport" |
14 | content="width=device-width"> |
15 | <title>Ejemplo</title> |
16 | </head> |
17 | <!-- |
18 | El elemento body es padre de los |
19 | elementos h1 y p. |
20 | --> |
21 | <body> |
22 | <h1>Ejemplo</h1> |
23 | <p>Hola mundo.👶</p> |
24 | </body> |
25 | </html> |
Un elemento es hijo de otro elemento si pertenece al contenido de este último.
1 | <!DOCTYPE html> |
2 | <!-- |
3 | El elemento html no es hijo de |
4 | nadie. |
5 | --> |
6 | <html lang="es"> |
7 | <!-- |
8 | El elemento head es hijo del |
9 | elemento html. |
10 | --> |
11 | <head> |
12 | <!-- |
13 | Los 2 elementos meta y el title |
14 | son hijos del elemento head. |
15 | --> |
16 | <meta charset="UTF-8"> |
17 | <meta name="viewport" |
18 | content="width=device-width"> |
19 | <title>Ejemplo</title> |
20 | </head> |
21 | <!-- |
22 | El elemento body es hijo del |
23 | elemento html. |
24 | --> |
25 | <body> |
26 | <!-- |
27 | Los elementos h1 y p son hijos |
28 | del elemento body. |
29 | --> |
30 | <h1>Ejemplo</h1> |
31 | <p>Hola mundo.👶</p> |
32 | </body> |
33 | </html> |
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.
En esta lección se introduce el doctype HTML.
Este ejemplo muestra la estructura básica de un archivo HTML.
En esta lección se explica dicha estructura.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>Hola Mundo</title> |
8 | </head> |
9 | <body> |
10 | 👽 ¡Hola Mundo! |
11 | </body> |
12 | </html> |
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.
1 | <html lang="es"> |
2 | <head> |
3 | ... |
4 | </head> |
5 | <body> |
6 | 👽 ¡Hola Mundo! |
7 | </body> |
8 | </html> |
La especificación técnica del elemento
html
está en
https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
head
El elemento
head
define la forma de procesar el archivo.
Es uno de los elementos hijos de
html
.
1 | <head> |
2 | <meta charset="UTF-8"> |
3 | <meta name="viewport" |
4 | content="width=device-width"> |
5 | <title>Hola Mundo</title> |
6 | </head> |
La especificación técnica del elemento
head
está en
https://html.spec.whatwg.org/multipage/semantics.html#the-head-element
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/.
1 | <meta charset="UTF-8"> |
La especificación técnica del elemento
meta
está en
https://html.spec.whatwg.org/multipage/semantics.html#the-meta-element.
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.
1 | <meta name="viewport" |
2 | content="width=device-width"> |
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.
1 | <title>Hola Mundo</title> |
La especificación técnica del elemento
title
está en
https://html.spec.whatwg.org/multipage/semantics.html#the-title-element
body
El elemento
body
define el contenido que se muestra.
1 | <body> |
2 | 👽 ¡Hola Mundo! |
3 | </body> |
La especificación técnica del elemento
body
está en
https://html.spec.whatwg.org/multipage/sections.html#the-body-element
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
;
1 | <body> |
2 | © < |
3 | </body> |
La especificación técnica de la referencia a caracter está en https://html.spec.whatwg.org/multipage/syntax.html#character-references
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.
En esta lección se introducen los elementos básicos de HTML.
Este es un ejemplo típico de un archivo HTML.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>🏡Estructura</title> |
9 | </head> |
10 | |
11 | <body> |
12 | <!-- Título en el contenido --> |
13 | <h1>🏡Estructura</h1> |
14 | <!-- Navegación --> |
15 | <nav> |
16 | <!-- Título de sección --> |
17 | <h2>Enlaces</h2> |
18 | <!-- Párrafo --> |
19 | <p> |
20 | <!-- hipervínculo --> |
21 | <a target="_blank" rel="noreferrer" |
22 | href=" https://google.com ">Google</a> |
23 | </p> |
24 | </nav> |
25 | <!-- Párrafos --> |
26 | <p>🌎Hola Mundo.</p> |
27 | <p>🧻Más texto.</p> |
28 | <p> |
29 | En HTML cuando varios |
30 | |
31 | saltos de línea |
32 | y espacios van juntos, se muestran como un solo espacio. |
33 | </p> |
34 | <p> |
35 | El texto fluye de forma responsiva, ocupando todo el espacio horizontal y |
36 | continuando en el siguiente renglón. |
37 | </p> |
38 | <p>Se recomienda que las líneas de código tengan un máximo de 80 caacteres.</p> |
39 | <!-- Pie de pagina --> |
40 | <footer> |
41 | <p> |
42 | © 2021 Gilberto Pacheco Gallegos. |
43 | </p> |
44 | </footer> |
45 | </body> |
46 | |
47 | </html> |
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.
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 MathMLmeta
(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 SVGtemplate
textarea
time
u
var
video
wbr
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.
1 | <h1>🏡Estructura</h1> |
2 | <nav> |
3 | <h2>Enlaces</h2> |
4 | ... |
5 | </nav> |
6 | ... |
La especificación técnica de los títulos está en https://html.spec.whatwg.org/multipage/sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements
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.
1 | <p>🌎Hola Mundo.</p> |
2 | <p>🧻Más texto.</p> |
La especificación técnica del elemento
p
está en
https://html.spec.whatwg.org/multipage/grouping-content.html#the-p-element
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
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.
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.
1 | <a target="_blank" rel="noreferrer" |
2 | href=" https://google.com ">Google</a> |
La especificación técnica del elemento
a
está en
https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-a-element
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.
1 | <nav> |
2 | <h2>Enlaces</h2> |
3 | <p> |
4 | <a target="_blank" rel="noreferrer" |
5 | href=" https://google.com ">Google</a> |
6 | </p> |
7 | </nav> |
La especificación técnica del elemento
nav
está en
https://html.spec.whatwg.org/multipage/sections.html#the-body-element
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
.
1 | <footer> |
2 | <p> |
3 | © 2021 |
4 | Gilberto Pacheco Gallegos. |
5 | </p> |
6 | </footer> |
La especificación técnica del elemento
footer
está en
https://html.spec.whatwg.org/multipage/sections.html#the-footer-element
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
En esta lección se muestran ejemplos típicos de HTML.
Este es un ejemplo típico de un documento HTML usando sessiones.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" content="width=device-width"> |
7 | <title>Secciones</title> |
8 | </head> |
9 | |
10 | <body> |
11 | <main> |
12 | <menu> |
13 | <li> |
14 | <button type="button" popovertarget="navGeneral">≡</button> |
15 | </li> |
16 | </menu> |
17 | <header> |
18 | <hgroup> |
19 | <h1>Secciones</h1> |
20 | <p>O como escribir mejor tus documentos.</p> |
21 | </hgroup> |
22 | <p> |
23 | En el <header> puedes colocar el título o información resumida sobre |
24 | el documento. |
25 | <nav> |
26 | <ol> |
27 | <li> |
28 | <p><a href="#secciones">Uso de secciones</a></p> |
29 | </li> |
30 | <li> |
31 | <p><a href="#otra">Otra sección</a></p> |
32 | </li> |
33 | </ol> |
34 | </nav> |
35 | </p> |
36 | </header> |
37 | <aside> |
38 | <h2>El elemento <aside></h2> |
39 | <p> |
40 | El elemento <dfn>aside</dfn> representa una sección de una página que |
41 | tiene contenido relacionado indirectamente con el contenido que lo rodea y |
42 | que podría considerarse independiente de dicho contenido. Estas secciones |
43 | suelen representarse como barras laterales en la tipografía impresa. |
44 | </p> |
45 | <p> |
46 | El elemento puede utilizarse para efectos tipográficos como citas destacadas |
47 | o barras laterales, para publicidad, para grupos de elementos de navegación |
48 | y para otro contenido que se considere independiente del contenido principal |
49 | de la página. |
50 | </p> |
51 | </aside> |
52 | <nav popover="auto" id="navGeneral"> |
53 | <h2>Enlaces externos</h2> |
54 | <ul> |
55 | <li> |
56 | <p> |
57 | <a target="_blank" rel="noreferrer" href="https://savethecat.com/"> |
58 | Salvar al gato. |
59 | </a> |
60 | </p> |
61 | </li> |
62 | <li> |
63 | <p> |
64 | <a target="_blank" rel="noreferrer" href="https://www.showrunner.xyz/"> |
65 | Showrunner |
66 | </a> |
67 | </p> |
68 | </li> |
69 | <li> |
70 | <p> |
71 | <a target="_blank" rel="noreferrer" href="https://google.com/"> |
72 | |
73 | </a> |
74 | </p> |
75 | </li> |
76 | </ul> |
77 | </nav> |
78 | <p> |
79 | Este es el contenido |
80 | principal de la página. |
81 | </p> |
82 | <p> |
83 | Cada párrafo representa una idea. |
84 | </p> |
85 | <p> |
86 | El contenido de un párrafo puede llevar juntos muchos espacios y saltos de |
87 | línea, pero se muestran como un solo espacio. |
88 | </p> |
89 | <p> |
90 | Para que esta página funcione correctamente debes tener actualizado tu |
91 | navegador. |
92 | </p> |
93 | <section id="secciones"> |
94 | <h2>Uso de secciones</h2> |
95 | <p> |
96 | puede llevar secciones. |
97 | Cada sección se usa para tocar un aspecto del contenido |
98 | general. |
99 | </p> |
100 | <p> |
101 | Las secciones se usan cuando el contenido es largo y/o complicado, siendo |
102 | mejor abordarlo por partes. |
103 | </p> |
104 | </section> |
105 | <section id="otra"> |
106 | <header> |
107 | <h2>Otra sección</h2> |
108 | <p> |
109 | Las secciones pueden llevar sus propios <header> y <footer> |
110 | </p> |
111 | </header> |
112 | Esta sección se usa para introducir una parte del contenido general. También |
113 | pueden llevar subsecciones. |
114 | <section> |
115 | <h3>Sub sección</h3> |
116 | <p> |
117 | Podemos poner distintos niveles de subsecciones. |
118 | </p> |
119 | </section> |
120 | <footer> |
121 | <p> |
122 | Este <footer> es parte de una sección. |
123 | </p> |
124 | </footer> |
125 | </section> |
126 | <article> |
127 | <h2>Un artículo</h2> |
128 | El elemento <article> representa una composición completa o autónoma en |
129 | un documento, página, aplicación o sitio web, y que, en principio, puede |
130 | distribuirse o reutilizarse de forma independiente. Puede ser una publicación |
131 | en un foro, un artículo de revista o periódico, una entrada de blog, un |
132 | comentario enviado por un usuario, un widget o gadget interactivo, o |
133 | cualquier otro elemento de contenido independiente. |
134 | </article> |
135 | <footer> |
136 | <p> |
137 | © 2025 Gilberto Pacheco Gallegos. |
138 | </p> |
139 | </footer> |
140 | </main> |
141 | </body> |
142 | |
143 | </html> |
En esta lección se mostró como usar secciones en HTML.
En esta lección se introduce el lenguaje 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/
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>CSS</title> |
8 | <style> |
9 | h1 { |
10 | color: yellow; |
11 | background-color: blue; |
12 | } |
13 | |
14 | p { |
15 | color: white; |
16 | background-color: black; |
17 | } |
18 | </style> |
19 | </head> |
20 | <body> |
21 | <h1>CSS</h1> |
22 | <p>Este es un ejemplo.</p> |
23 | <p>Aprende CSS.</p> |
24 | <h2>Subsección</h2> |
25 | <p>Juega con colores.</p> |
26 | <footer> |
27 | <p> |
28 | © 2021 |
29 | Gilberto Pacheco Gallegos. |
30 | </p> |
31 | </footer> |
32 | </body> |
33 | </html> |
La sintacis de CSS3 está en https://www.w3.org/TR/css-syntax-3/
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>CSS</title> |
8 | <style> |
9 | h1 { |
10 | color: yellow; |
11 | background-color: blue; |
12 | } |
13 | |
14 | p { |
15 | color: white; |
16 | background-color: black; |
17 | } |
18 | </style> |
19 | </head> |
20 | <body> |
21 | ... |
22 | </body> |
23 | </html> |
Los comentarios inician con
/*
y terminan con
*/
.
Pueden ocupar más de un renglón.
Se colocan dentro de un elemento
style
.
1 | <style> |
2 | /* Comentario sobre h1. */ |
3 | h1 { |
4 | color: yellow; /*Sobre color.*/ |
5 | background-color: blue; |
6 | } |
7 | </style> |
Una expresión que permite identificar a uno o varios elementos de HTML.
Una secuencia de selectores separadas por coma
(,
).
Una expresión del tipo
nombre: valor
Una secuencia de declaraciones de propiedades separadas por punto
y coma
(;
)
y encerradas entre llaves
({
}
).
Une lista de selectores con una lista de declaraciones de propiedades.
La definición de una regla de estilo está en https://www.w3.org/TR/css-syntax-3/#style-rule
1 | <style> |
2 | /* Esta es una regla. |
3 | * El selector es h1. |
4 | * Sus propiedades están dentro de |
5 | * las llaves. */ |
6 | h1 { |
7 | color: yellow; |
8 | background-color: blue; |
9 | } /* Fin de la primera regla. */ |
10 | |
11 | /* Esta es otra regla. |
12 | * El selector es p. |
13 | * Sus propiedades están dentro de |
14 | * las llaves. */ |
15 | p { |
16 | color: white; |
17 | background-color: black; |
18 | } /* Fin de la segunda regla. */ |
19 | </style> |
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
1 | <head> |
2 | <style> |
3 | /* El selector |
4 | * h1 |
5 | * hace que las propiedades de |
6 | * esta regla se apliquen a todos |
7 | * los elementos de tipo |
8 | * h1. */ |
9 | h1 { |
10 | color: yellow; |
11 | background-color: blue; |
12 | } |
13 | |
14 | /* El selector |
15 | * p |
16 | * hace que las propiedades de |
17 | * esta regla se apliquen a todos |
18 | * los elementos de tipo |
19 | * p. */ |
20 | p { |
21 | color: white; |
22 | background-color: black; |
23 | } |
24 | </style> |
25 | </head> |
26 | <body> |
27 | <!-- Las reglas con el selector |
28 | h1 |
29 | se aplican a este elemento. --> |
30 | <body> |
31 | <h1>CSS</h1> |
32 | <!-- Las reglas con el selector |
33 | p |
34 | se aplican a este elemento. --> |
35 | <p>Este es un ejemplo.</p> |
36 | <!-- Las reglas con el selector |
37 | p |
38 | se aplican a este elemento. --> |
39 | <p>Aprende CSS.</p> |
40 | <h2>Subsección</h2> |
41 | <!-- Las reglas con el selector |
42 | p |
43 | se aplican a este elemento. --> |
44 | <p>Juega con colores.</p> |
45 | <footer> |
46 | <!-- Las reglas con el selector |
47 | p |
48 | se aplican a este elemento. --> |
49 | <p> |
50 | © 2021 |
51 | Gilberto Pacheco Gallegos. |
52 | </p> |
53 | </footer> |
54 | </body> |
Se declaran con una expresión del tipo
nombre: valor
1 | <head> |
2 | <style> |
3 | h1 { |
4 | /* Esta es la propiedad |
5 | * color. |
6 | * En este caso se aplica |
7 | * a los elementos tipo |
8 | * h1. |
9 | * Su valor es yellow. */ |
10 | color: yellow; |
11 | /* Esta es la propiedad |
12 | * background-color. |
13 | * En este caso se aplica |
14 | * a los elementos tipo |
15 | * h1. |
16 | * Su valor es blue. */ |
17 | background-color: blue; |
18 | } |
19 | |
20 | p { |
21 | /* Esta es la propiedad |
22 | * color. |
23 | * En este caso se aplica |
24 | * a los elementos tipo |
25 | * p. |
26 | * Su valor es white. */ |
27 | color: white; |
28 | /* Esta es la propiedad |
29 | * background-color. |
30 | * En este caso se aplica |
31 | * a los elementos tipo |
32 | * p. |
33 | * Su valor es black. */ |
34 | background-color: black; |
35 | } |
36 | </style> |
37 | </head> |
38 | <body> |
39 | <h1>CSS</h1> |
40 | <p>Este es un ejemplo.</p> |
41 | <p>Aprende CSS.</p> |
42 | <h2>Subsección</h2> |
43 | <p>Juega con colores.</p> |
44 | <footer> |
45 | <p> |
46 | © 2021 |
47 | Gilberto Pacheco Gallegos. |
48 | </p> |
49 | </footer> |
50 | </body> |
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)
.
1 | <head> |
2 | <style> |
3 | html { |
4 | --colTexto: yellow; |
5 | --colFondo: blue; |
6 | } |
7 | |
8 | h1 { |
9 | color: var(--colTexto); |
10 | background-color: |
11 | var(--colFondo); |
12 | } |
13 | |
14 | p { |
15 | color: var(--colTexto); |
16 | background-color: black; |
17 | } |
18 | </style> |
19 | </head> |
20 | <body> |
21 | <h1>CSS</h1> |
22 | <p>Este es un ejemplo.</p> |
23 | <p>Aprende CSS.</p> |
24 | <h2>Subsección</h2> |
25 | <p>Juega con colores.</p> |
26 | <footer> |
27 | <p> |
28 | © 2021 |
29 | Gilberto Pacheco Gallegos. |
30 | </p> |
31 | </footer> |
32 | </body> |
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.
En esta lección se presentan las propiedades básicas de CSS.
Cada símbolo que se puede representar en una familia de fuentes se conoce como glifo o pictograma.
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.
font-family
Define el tipo de letra.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>font-family</title> |
8 | <style> |
9 | h1 { |
10 | font-family: sans-serif |
11 | } |
12 | |
13 | p { |
14 | font-family: serif |
15 | } |
16 | </style> |
17 | </head> |
18 | <body> |
19 | <h1>font-family sans-serif</h1> |
20 | <p>font-family serif.</p> |
21 | </body> |
22 | </html> |
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)
Estas son algunas formas de expresar los colores primarios en las definiciones que aparecen después:
Valor decimal entre 0 y 255. Indica la cantidad de rojo que lleva un color.
Valor decimal entre 0 y 255. Indica indica la cantidad de verde que lleva un color.
Valor decimal entre 0 y 255. Indica la cantidad de azul que lleva un color.
Valor decimal fraccionario entre 0 y 1. Indica lo transparente que es un color: 0 - totalmente transparente, 1 - totalmente opaco.
Valor de 2 cifras hexadecimales entre 00 y ff. Indica la cantidad de rojo que lleva un color.
Valor de 2 cifras hexadecimales entre 00 y ff. Indica la cantidad de verde que lleva un color.
Valor de 2 cifras hexadecimales entre 00 y ff. Indica la cantidad de azul que lleva un color.
Valor de 2 cifras hexadecimales entre 00 y ff. Indica lo transparente que es un color. 00 - totalmente transparente, ff - totalmente opaco.
transparent
Color transparente.
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
Representa la mezcla de rojo, verde, azul y transparencia en notación hexadecimal.
Ejemplo:
#0b467380
Una herramienta muy interesante para el uso de colores en sitios web es https://paletton.com/
color
Especificar el color del trazo, por ejemplo, del texto.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>Color</title> |
8 | <style> |
9 | h1 { |
10 | color: blue |
11 | } |
12 | |
13 | p { |
14 | color: #005500 |
15 | } |
16 | </style> |
17 | </head> |
18 | <body> |
19 | <h1>Color blue</h1> |
20 | <p>Color #005500.</p> |
21 | </body> |
22 | </html> |
La especificación técnica de la propiedad
color
está en
https://www.w3.org/TR/css-color-3/#color0
background-color
Especifica el color del fondo de un elemento.
La definición de la propiedad
background-color
está en
https://www.w3.org/TR/css-backgrounds-3/#the-background-color
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>background-color</title> |
8 | <style> |
9 | h1 { |
10 | background-color: yellow |
11 | } |
12 | |
13 | p { |
14 | background-color: #aaffaa |
15 | } |
16 | </style> |
17 | </head> |
18 | <body> |
19 | <h1>background-color yellow</h1> |
20 | <p>background-color #aaffaa.</p> |
21 | </body> |
22 | </html> |
La especificación técnica de la propiedad
background-color
está en
https://www.w3.org/TR/css-backgrounds-3/#the-background-color
En esta lección se definieron los siguientes conceptos:
Fonts.
La propiedad font-family
.
Colores en CSS
La propiedad color
La propiedad background-color
.
display
En esta lección se presenta el concepto de polimorfismo.
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>div</title> |
8 | <style> |
9 | div { |
10 | color: chocolate; |
11 | } |
12 | </style> |
13 | </head> |
14 | <body> |
15 | <div>Un div simple.</div> |
16 | <div>Otro div simple.</div> |
17 | <p>Un párrafo simple.</p> |
18 | <p>Otro párrafo simple.</p> |
19 | </body> |
20 | </html> |
La especificación técnica del elemento
div
está en
https://html.spec.whatwg.org/multipage/grouping-content.html#the-div-element
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>span</title> |
8 | <style> |
9 | span { |
10 | color: magenta; |
11 | } |
12 | </style> |
13 | </head> |
14 | <body> |
15 | <p> |
16 | Hola, |
17 | <span>este es un span.</span> |
18 | Más texto |
19 | <span>otro span.</span> |
20 | </p> |
21 | <p>Otro párrafo simple.</p> |
22 | </body> |
23 | </html> |
La especificación técnica del elemento
span
está en
https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-span-element
display
Indica la forma en que un elemento se depliega.
La definición oficial de esta propiedad está en proceso de cambio. Aqupi se muestran los valores que funcioan mejor al momento de escribir estas notas.
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.
none
El elemento completo, incluyendo todo su contenido, el contenido de su contenido y así sucesivamente no se muestra, incluyendo texto y cajas.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>inline</title> |
8 | <style> |
9 | div { |
10 | display: none |
11 | } |
12 | </style> |
13 | </head> |
14 | <body> |
15 | <p>Ahora me ves.</p> |
16 | <div>Ahora no me ves.</div> |
17 | </body> |
18 | </html> |
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>inline</title> |
8 | <style> |
9 | p { |
10 | display: inline; |
11 | color: olive |
12 | } |
13 | </style> |
14 | </head> |
15 | <body> |
16 | <div> |
17 | El texto es inline. |
18 | El texto es inline. |
19 | El texto es inline. |
20 | El texto es inline. |
21 | El texto es inline. |
22 | <span>El span es inline.</span> |
23 | <p> |
24 | Este párrafo es forzado a ser |
25 | inline. |
26 | </p> |
27 | <em> |
28 | Esto es texto con énfasis. |
29 | </em> |
30 | <strong> |
31 | Esto es texto con énfasis |
32 | fuerte. |
33 | </strong> |
34 | Más texto. |
35 | Más texto. |
36 | Más texto. |
37 | Más texto. |
38 | </div> |
39 | </body> |
40 | </html> |
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
.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>block</title> |
8 | <style> |
9 | div { |
10 | background-color: yellow; |
11 | } |
12 | </style> |
13 | </head> |
14 | <body> |
15 | <h1>block</h1> |
16 | <p> |
17 | En este ejemplo, body solo |
18 | tiene elementos de bloque. |
19 | </p> |
20 | <p> |
21 | Este párrafo solo tiene contenido |
22 | inline e inline-block. |
23 | <em>Un énfasis inline.</em> |
24 | <button> |
25 | Un botón inline-block, |
26 | inline-block, inline-block |
27 | </button> |
28 | <span> |
29 | Un span inline, inline, inline, |
30 | inline. |
31 | </span> |
32 | </p> |
33 | <div> |
34 | Este div tiene contenido |
35 | mezclado. |
36 | <em> |
37 | Este es un énfasis inline. |
38 | </em> |
39 | <strong> |
40 | Este es un strong inline. |
41 | </strong> |
42 | <button> |
43 | Este es un botón inline-block |
44 | </button> |
45 | <p> |
46 | Este párrafo solo contiene |
47 | inline e inline-block. |
48 | <em>Un énfasis inline.</em> |
49 | <button> |
50 | Un botón inline-block |
51 | </button> |
52 | <span>Un span inline.</span> |
53 | </p> |
54 | </div> |
55 | </body> |
56 | </html> |
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
.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>inline-block</title> |
8 | <style> |
9 | span { |
10 | display: inline-block; |
11 | background-color: yellow; |
12 | } |
13 | </style> |
14 | </head> |
15 | <body> |
16 | <p> |
17 | Texto, texto, texto |
18 | <span> |
19 | Este es un span forzado a ser |
20 | inline-block, inline-block, |
21 | inline-block, inline-block. |
22 | </span> |
23 | <button> |
24 | Este es un botón inline-block, |
25 | inline-block, inline-block. |
26 | </button> |
27 | </p> |
28 | </body> |
29 | </html> |
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
.
En esta lección se presenta el concepto de excepciones y como procesarlas.
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.
La especificación técnica de llas logitudes de CSS está en https://drafts.csswg.org/css-values/#lengths
Es un espacio transparente que separa un elemento de otro.
Es una línea (que puede ser una figura con adornos) alrededor de un elemento.
Es una espacio entre el contenido y el borde. Su color de fondo es el mismo que el color de fondo del contenido.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>Modelo de cajas</title> |
8 | <style> |
9 | div { |
10 | margin: 1.5rem; |
11 | border: thick solid burlywood; |
12 | background-color: greenyellow; |
13 | } |
14 | </style> |
15 | </head> |
16 | <body> |
17 | <div>Contenido</div> |
18 | </body> |
19 | </html> |
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>Modelo de cajas</title> |
8 | <style> |
9 | div { |
10 | margin: 1.5rem; |
11 | border: thick solid burlywood; |
12 | background-color: greenyellow; |
13 | } |
14 | </style> |
15 | </head> |
16 | <body> |
17 | <div>Contenido</div> |
18 | </body> |
19 | </html> |
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>Relleno</title> |
8 | <style> |
9 | h1 { |
10 | padding-top: 0.5rem; |
11 | padding-left: 1rem; |
12 | padding-bottom: 1.5rem; |
13 | padding-right: 2rem; |
14 | background-color: cyan; |
15 | } |
16 | |
17 | p { |
18 | padding: 0.5rem 2rem; |
19 | background-color: yellow; |
20 | } |
21 | |
22 | div { |
23 | padding: 1rem; |
24 | background-color: red; |
25 | } |
26 | |
27 | footer { |
28 | padding: |
29 | 0.5rem 1rem 3rem 2rem; |
30 | background-color: |
31 | yellowgreen; |
32 | } |
33 | </style> |
34 | </head> |
35 | <body> |
36 | <h1>Relleno</h1> |
37 | <p>Párrafo</p> |
38 | <div>Div</div> |
39 | <footer>Footer</footer> |
40 | </body> |
41 | </html> |
Puede expresarse como un tamaño o con alguno de estos valores:
thin
medium
thick
Si no se pone, su valor por omisión es:
medium
.
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
.
Se especifica como un color cualquiera.
Si no se pone, su valor por omisión es el color del texto del elemento.
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.
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>Bordes</title> |
8 | <style> |
9 | h1 { |
10 | border-top-width: thin; |
11 | border-top-style: solid; |
12 | border-top-color: cyan; |
13 | border-left: |
14 | medium dashed red; |
15 | border-right: |
16 | thick dotted green; |
17 | border-bottom: |
18 | thick double blue |
19 | } |
20 | |
21 | nav { |
22 | border: thick groove cyan |
23 | } |
24 | |
25 | p { |
26 | border: thick ridge pink |
27 | } |
28 | |
29 | div { |
30 | border: thick inset yellowgreen |
31 | } |
32 | |
33 | footer { |
34 | border: thick outset orange |
35 | } |
36 | </style> |
37 | </head> |
38 | <body> |
39 | <h1>Bordes</h1> |
40 | <nav>Groove</nav> |
41 | <p>Ridge</p> |
42 | <div>Inset</div> |
43 | <footer>Outset</footer> |
44 | </body> |
45 | </html> |
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width, |
7 | initial-scale=1.0"> |
8 | <title>border-radius</title> |
9 | <style> |
10 | body { |
11 | color:yellow |
12 | } |
13 | |
14 | h1 { |
15 | background-color: blue; |
16 | border-top-right-radius: 10px; |
17 | border-top-left-radius: 5px; |
18 | border-bottom-right-radius: |
19 | 20px; |
20 | border-bottom-left-radius: |
21 | 2rem |
22 | } |
23 | |
24 | div { |
25 | background-color: royalblue; |
26 | padding: 0.5rem 1rem; |
27 | border-radius: 30px |
28 | } |
29 | |
30 | p { |
31 | background-color: blueviolet; |
32 | padding: 0.5rem 1.5rem; |
33 | border-radius: |
34 | 10px 20px 30px 40px; |
35 | } |
36 | </style> |
37 | </head> |
38 | <body> |
39 | <h1>border-radius</h1> |
40 | <div>Esquinas</div> |
41 | <p>Redondas</p> |
42 | </body> |
43 | </html> |
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width, |
7 | initial-scale=1.0"> |
8 | <title>box-sizing</title> |
9 | <style> |
10 | main { |
11 | width: 50%; |
12 | height: 15rem; |
13 | background-color: orange; |
14 | padding-top: 1rem; |
15 | padding-bottom: 1rem; |
16 | } |
17 | |
18 | h1 { |
19 | width: 100%; |
20 | background-color: lightgreen; |
21 | margin: 0; |
22 | font-size: 1rem; |
23 | padding: 1em; |
24 | border: thick solid green; |
25 | } |
26 | |
27 | nav { |
28 | box-sizing: content-box; |
29 | width: 100%; |
30 | background-color: pink; |
31 | padding: 1em; |
32 | border: thick solid red; |
33 | } |
34 | |
35 | p { |
36 | box-sizing: content-box; |
37 | width: 100%; |
38 | background-color: violet; |
39 | margin: 0; |
40 | } |
41 | |
42 | div { |
43 | box-sizing: border-box; |
44 | width: 100%; |
45 | background-color: lightblue; |
46 | padding: 1em; |
47 | border: thick solid blue; |
48 | } |
49 | </style> |
50 | </head> |
51 | <body> |
52 | <main> |
53 | <h1>por omisión</h1> |
54 | <nav>content-box</nav> |
55 | <p>content-box 2</div> |
56 | <div>border-box</div> |
57 | </main> |
58 | </body> |
59 | </html> |
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.
En esta lección se presenta el concepto 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.
fixed
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title> |
8 | Posicionamiento fixed |
9 | </title> |
10 | <style> |
11 | span { |
12 | position: fixed; |
13 | top: 0; |
14 | right: 0; |
15 | background-color: yellow; |
16 | } |
17 | </style> |
18 | </head> |
19 | <body> |
20 | <h1> |
21 | Posicionamiento |
22 | <span>fixed</span> |
23 | </h1> |
24 | </body> |
25 | </html> |
relative
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title> |
8 | Posicionamiento relative |
9 | </title> |
10 | <style> |
11 | span { |
12 | position: relative; |
13 | top: 1rem; |
14 | left: 1rem; |
15 | background-color: yellow; |
16 | } |
17 | </style> |
18 | </head> |
19 | <body> |
20 | <h1> |
21 | Posicionamiento |
22 | <span>relative</span> |
23 | </h1> |
24 | </body> |
25 | </html> |
absolute
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title> |
8 | Posicionamiento absolute |
9 | </title> |
10 | <style> |
11 | h1 { |
12 | position: absolute; |
13 | bottom: 0; |
14 | height: 6rem; |
15 | left: 2rem; |
16 | right: 2rem; |
17 | background-color: yellow; |
18 | } |
19 | |
20 | p { |
21 | position: relative; |
22 | background-color: chartreuse |
23 | } |
24 | |
25 | footer { |
26 | position: fixed; |
27 | top: 0; |
28 | right: 0; |
29 | width: 10rem; |
30 | background-color: yellow; |
31 | } |
32 | |
33 | span { |
34 | position: absolute; |
35 | top: 0; |
36 | left: 0; |
37 | background-color: cyan; |
38 | } |
39 | </style> |
40 | </head> |
41 | <body> |
42 | <h1> |
43 | Posicionamiento |
44 | <span>absolute (h1)</span> |
45 | </h1> |
46 | Bla, bla, bla |
47 | <p> |
48 | Párrafo relative con |
49 | <span>absolute (p)</span> |
50 | </p> |
51 | <div> |
52 | Este div contiene |
53 | <span>absolute (div)</span> |
54 | </div> |
55 | <footer> |
56 | Este footer lleva otro |
57 | <span>absolute (footer)</span> |
58 | </footer> |
59 | </body> |
60 | </html> |
sticky
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title> |
8 | Posicionamiento sticky |
9 | </title> |
10 | <style> |
11 | h1 { |
12 | /* Algunas versiones de Safari |
13 | * no soportan "sticky", pero sí |
14 | * "-webkit-sticky". */ |
15 | position: -webkit-sticky; |
16 | position: sticky; |
17 | top: 1rem; |
18 | background-color: yellow; |
19 | } |
20 | </style> |
21 | </head> |
22 | <body> |
23 | <h1>Posicionamiento sticky</h1> |
24 | <ol> |
25 | <li>X</li> |
26 | <li>X</li> |
27 | <li>X</li> |
28 | <li>X</li> |
29 | <li>X</li> |
30 | <li>X</li> |
31 | <li>X</li> |
32 | <li>X</li> |
33 | <li>X</li> |
34 | <li>X</li> |
35 | <li>X</li> |
36 | <li>X</li> |
37 | <li>X</li> |
38 | <li>X</li> |
39 | <li>X</li> |
40 | <li>X</li> |
41 | <li>X</li> |
42 | <li>X</li> |
43 | <li>X</li> |
44 | <li>X</li> |
45 | <li>X</li> |
46 | <li>X</li> |
47 | <li>X</li> |
48 | <li>X</li> |
49 | <li>X</li> |
50 | <li>X</li> |
51 | <li>X</li> |
52 | <li>X</li> |
53 | <li>X</li> |
54 | <li>X</li> |
55 | <li>X</li> |
56 | <li>X</li> |
57 | <li>X</li> |
58 | <li>X</li> |
59 | <li>X</li> |
60 | <li>X</li> |
61 | <li>X</li> |
62 | <li>X</li> |
63 | </ol> |
64 | </body> |
65 | </html> |
En esta lección se revisaron los siguientes conceptos:
Propiedades de posicionamiento
El posicionamiento fixed
El posicionamiento relative
El posicionamiento absolute
El posicionamiento sticky
En esta lección se presentan algunos selectores de CSS.
*
Selecciona todos los elementos.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>Selector *</title> |
8 | <style> |
9 | * { |
10 | /* Texto centrado. */ |
11 | text-align: center; |
12 | } |
13 | </style> |
14 | </head> |
15 | <body> |
16 | <h1>Selector *</h1> |
17 | <p>Hola.</p> |
18 | </body> |
19 | </html> |
#identificador
Selecciona el valor del atributo id.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title> |
8 | Selector #identificador |
9 | </title> |
10 | <style> |
11 | /* Seleciona el elemento con |
12 | * id="neg" */ |
13 | #neg { |
14 | /* negritas */ |
15 | font-weight: bold; |
16 | } |
17 | |
18 | /* Seleciona el elemento de tipo |
19 | * p |
20 | * con |
21 | * id="otro" */ |
22 | p#otro { |
23 | /* mayúsculas */ |
24 | text-transform: uppercase; |
25 | } |
26 | |
27 | /* Seleciona el elemento de tipo |
28 | * h1 |
29 | * con |
30 | * id="chas". |
31 | * No se aplica porque el único |
32 | * elemento con |
33 | * id="chas" |
34 | * es de tipo |
35 | * p */ |
36 | h1#chas { |
37 | color: green; |
38 | } |
39 | </style> |
40 | </head> |
41 | <body> |
42 | <h1>Selector #identificador</h1> |
43 | <p>Uno.</p> |
44 | <p id="chas">Dos.</p> |
45 | <p>Tres.</p> |
46 | <p id="otro">Cuatro.</p> |
47 | </body> |
48 | </html> |
.clase
Seleciona los elementos cuyo atributo
class
contenga el identificador después del punto
(.
).
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>Selector .clase</title> |
8 | <style> |
9 | /* Seleciona los elementos cuyo |
10 | * atributo |
11 | * class |
12 | * contenga el identificador |
13 | * azu */ |
14 | .azu { |
15 | color: blue; |
16 | } |
17 | |
18 | /* Seleciona los elementos cuyo |
19 | * atributo |
20 | * class |
21 | * contenga los identificadores |
22 | * ama y azu */ |
23 | .ama.azu { |
24 | /* letra itálica */ |
25 | font-style: oblique; |
26 | } |
27 | |
28 | /* Seleciona los elementos tipo |
29 | * p |
30 | * cuyo atributo |
31 | * class |
32 | * contenga el identificador |
33 | * ama */ |
34 | p.ama { |
35 | background-color: yellow; |
36 | } |
37 | |
38 | /* Seleciona los elementos tipo |
39 | * p |
40 | * cuyo atributo |
41 | * class |
42 | * contenga los identificadores |
43 | * ama y ver */ |
44 | p.ama.ver { |
45 | /* Alínea el texto al final de |
46 | * la línea. */ |
47 | text-align: end; |
48 | } |
49 | </style> |
50 | </head> |
51 | <body> |
52 | <h1 class="ama azu"> |
53 | Selector .clase |
54 | </h1> |
55 | <p class="ver azu ama"> |
56 | Uno. |
57 | </p> |
58 | <p class="azu">Dos.</p> |
59 | <p>Tres.</p> |
60 | <p class="ama">Cuatro.</p> |
61 | <p class="ama ver">Cinco.</p> |
62 | <footer class="azu"> |
63 | <p> |
64 | © 2021 |
65 | Gilberto Pacheco Gallegos. |
66 | </p> |
67 | </footer> |
68 | </body> |
69 | </html> |
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title> |
8 | Selector sel1 > sel2 |
9 | </title> |
10 | <style> |
11 | /* Selecciona todos los |
12 | * em |
13 | * que sean hijos directos de |
14 | * p */ |
15 | p>em { |
16 | background-color: yellow; |
17 | } |
18 | </style> |
19 | </head> |
20 | <body> |
21 | <h1> |
22 | Selector |
23 | <em>sel1</em> |
24 | <strong>></strong> |
25 | <em>sel2</em> |
26 | </h1> |
27 | <p> |
28 | <strong> |
29 | Énfasis fuerte. |
30 | </strong> |
31 | <em>Énfasis.</em> |
32 | Más texto. |
33 | <span> |
34 | <em>Otro énfasis.</em> |
35 | <strong> |
36 | Otro énfasis fuerte. |
37 | </strong> |
38 | <span> |
39 | <em>Hola.</em> |
40 | <strong>Adios.</strong> |
41 | </span> |
42 | </span> |
43 | </p> |
44 | <footer> |
45 | <p> |
46 | <em>© 2021</em> |
47 | Gilberto Pacheco Gallegos. |
48 | </p> |
49 | </footer> |
50 | </body> |
51 | </html> |
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title> |
8 | Selector sel1 sel2 |
9 | </title> |
10 | <style> |
11 | /* Selecciona todos los |
12 | * em |
13 | * que sean descendientes en |
14 | * cualquier nivel de |
15 | * anidamiento de |
16 | * p */ |
17 | p em { |
18 | background-color: yellow; |
19 | } |
20 | </style> |
21 | </head> |
22 | <body> |
23 | <h1> |
24 | Selector |
25 | <em>sel1</em> |
26 | <em>sel2</em> |
27 | </h1> |
28 | <p> |
29 | <strong> |
30 | Énfasis fuerte. |
31 | </strong> |
32 | <em>Énfasis.</em> |
33 | Más texto. |
34 | <span> |
35 | <em>Otro énfasis.</em> |
36 | <strong> |
37 | Otro énfasis fuerte. |
38 | </strong> |
39 | <span> |
40 | <em>Hola.</em> |
41 | <strong>Adios.</strong> |
42 | </span> |
43 | </span> |
44 | </p> |
45 | <footer> |
46 | <p> |
47 | <em>© 2021</em> |
48 | Gilberto Pacheco Gallegos. |
49 | </p> |
50 | </footer> |
51 | </body> |
52 | </html> |
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title> |
8 | Selector sel1 + sel2 |
9 | </title> |
10 | <style> |
11 | /* Selecciona todos los |
12 | * strong |
13 | * inmediatamente después de |
14 | * em */ |
15 | em+strong { |
16 | background-color: yellow; |
17 | } |
18 | </style> |
19 | </head> |
20 | <body> |
21 | <h1> |
22 | Selector |
23 | <em>sel1</em> |
24 | <strong>+</strong> |
25 | <em>sel2</em> |
26 | </h1> |
27 | <p> |
28 | <em>Este</em> |
29 | <strong>ejercicio</strong> |
30 | está |
31 | <em>muy</em> |
32 | divertido |
33 | <strong>ggg</strong> |
34 | <em>jajaja</em> |
35 | <!-- subíndice --> |
36 | <sub>jejeje</sub> |
37 | <strong>jijiji</strong> |
38 | 🤣🤣🤣. |
39 | </p> |
40 | </body> |
41 | </html> |
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title> |
8 | Selector sel1 ~ sel2 |
9 | </title> |
10 | <style> |
11 | /* Selecciona todos los |
12 | * strong |
13 | * hermanos después de |
14 | * em */ |
15 | em~strong { |
16 | background-color: yellow; |
17 | } |
18 | </style> |
19 | </head> |
20 | <body> |
21 | <h1> |
22 | Selector |
23 | <em>sel1</em> |
24 | <strong>~</strong> |
25 | <em>sel2</em> |
26 | </h1> |
27 | <p> |
28 | <em>Este</em> |
29 | <strong>ejercicio</strong> |
30 | está |
31 | <em>muy</em> |
32 | divertido |
33 | <strong>ggg</strong> |
34 | <em>jajaja</em> |
35 | <!-- superíndice --> |
36 | <sup>jejeje</sup> |
37 | <strong>jijiji</strong> |
38 | 🤣🤣🤣. |
39 | </p> |
40 | </body> |
41 | </html> |
sel1 , sel2
Seleciona los elementos que cumplan con cualquiera de los selectores que
aparecen separados por coma
(,
).
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title> |
8 | Selector sel1 , sel2 |
9 | </title> |
10 | <style> |
11 | /* Selecciona todos los |
12 | * h1, div y nav */ |
13 | h1, |
14 | div, |
15 | nav { |
16 | background-color: yellow; |
17 | } |
18 | </style> |
19 | </head> |
20 | <body> |
21 | <h1>Selector sel1 , sel2</h1> |
22 | <p>Hola.</p> |
23 | <nav>Navegación.</nav> |
24 | <div>Adios.</div> |
25 | </body> |
26 | </html> |
:active
Seleciona los elementos que estén activos; por ejemplo al hacerles clic.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>Selector :active</title> |
8 | <style> |
9 | :active { |
10 | color: blue; |
11 | } |
12 | |
13 | span:active { |
14 | background-color: yellow; |
15 | } |
16 | </style> |
17 | </head> |
18 | <body> |
19 | <h1>Selector :active</h1> |
20 | <p><button>Haz Click</button></p> |
21 | <p><span>Haz Click</span></p> |
22 | </body> |
23 | </html> |
: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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>Selector :focus</title> |
8 | <style> |
9 | :focus { |
10 | color: red; |
11 | } |
12 | |
13 | input:focus { |
14 | background-color: yellow; |
15 | } |
16 | |
17 | textarea, |
18 | input { |
19 | display: block; |
20 | } |
21 | </style> |
22 | </head> |
23 | <body> |
24 | <h1>Selector :focus</h1> |
25 | <p> |
26 | <label> |
27 | Nombre |
28 | <input> |
29 | </label> |
30 | </p> |
31 | <p> |
32 | <label> |
33 | Relato |
34 | <textarea></textarea> |
35 | </label> |
36 | </p> |
37 | <p> |
38 | <span>Intenta teclear</span> |
39 | </p> |
40 | </body> |
41 | </html> |
style
Todos los elementos pueden definir su propio estilo usando el atributo
style
.
Las propiedades colocadas en este atributo sustituyen a los valores definidos en otros lados.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Atrinuto style</title> |
9 | <style> |
10 | p { |
11 | color: olive; |
12 | font-style: italic; |
13 | } |
14 | </style> |
15 | </head> |
16 | |
17 | <body> |
18 | <p style="color: yellow; |
19 | background-color: blue"> |
20 | Párrafo de letra amarilla y fondo |
21 | azul. |
22 | </p> |
23 | <p>Párrafo normal.</p> |
24 | </body> |
25 | |
26 | </html> |
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
.
En esta lección se muestran ejemplos típicos de HTML.
float
11 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>Float</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | nav { |
13 | float: inline-start; |
14 | border: solid; |
15 | } |
16 | |
17 | aside { |
18 | float: inline-end; |
19 | border: solid; |
20 | } |
21 | |
22 | footer { |
23 | clear: both; |
24 | } |
25 | </style> |
26 | |
27 | </head> |
28 | |
29 | <body> |
30 | |
31 | <h1>Float</h1> |
32 | |
33 | <nav> |
34 | <p> |
35 | Flota al inicio. |
36 | </p> |
37 | <p> |
38 | <a href="https://facebook.com" |
39 | target="_blank" |
40 | rel="noreferrer"> |
41 | Facebook</a> |
42 | </p> |
43 | </nav> |
44 | |
45 | <aside> |
46 | <p> |
47 | Flota al final. |
48 | </p> |
49 | </aside> |
50 | |
51 | <p>Este ejemplo usa float.</p> |
52 | <p> |
53 | El párrafo que sigue te muestra |
54 | como flota el texto. |
55 | </p> |
56 | |
57 | <footer> |
58 | <p> |
59 | El flotado se detiene con |
60 | clear: both. |
61 | </p> |
62 | <p> |
63 | © 2025 |
64 | Gilberto Pacheco Gallegos |
65 | </p> |
66 | </footer> |
67 | |
68 | </body> |
69 | |
70 | </html> |
La propiedad float en CSS Tricks: https://css-tricks.com/almanac/properties/f/float/
float
21 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>Float 2</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | main { |
13 | display: flow-root; |
14 | } |
15 | |
16 | aside { |
17 | border: solid; |
18 | } |
19 | |
20 | .floatLeft { |
21 | float: left |
22 | } |
23 | |
24 | .floatRight { |
25 | float: right |
26 | } |
27 | </style> |
28 | |
29 | </head> |
30 | |
31 | <body> |
32 | |
33 | <h1>Float 2</h1> |
34 | |
35 | <main> |
36 | |
37 | <aside class="floatLeft"> |
38 | <p>Flota a la izquierda.</p> |
39 | </aside> |
40 | |
41 | <aside class="floatRight"> |
42 | <p>Flota a la derecha.</p> |
43 | </aside> |
44 | |
45 | <p> |
46 | Este es otro ejemplo de float. |
47 | </p> |
48 | <p> |
49 | La propiedad display: flow-root |
50 | evita el flotado fuera del |
51 | elemento. |
52 | </p> |
53 | <p> |
54 | Puedes poner varios float hacia |
55 | donde quieras; inclusive hacia |
56 | el mismo lado. |
57 | </p> |
58 | |
59 | <aside class="floatRight"> |
60 | <p>Flota a la derecha.</p> |
61 | </aside> |
62 | |
63 | </main> |
64 | |
65 | <footer> |
66 | <p> |
67 | © 2025 |
68 | Gilberto Pacheco Gallegos |
69 | </p> |
70 | </footer> |
71 | |
72 | </body> |
73 | |
74 | </html> |
La propiedad float en Mozilla Developer Network: https://developer.mozilla.org/es/docs/Web/CSS/float
float
31 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>Float 3</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | p { |
13 | clear: both; |
14 | } |
15 | |
16 | p::first-letter { |
17 | font-weight: bold; |
18 | font-size: 3rem; |
19 | float: inline-start; |
20 | } |
21 | </style> |
22 | |
23 | </head> |
24 | |
25 | <body> |
26 | |
27 | <h1>Float 3</h1> |
28 | |
29 | <p> |
30 | Este es otro ejemplo de float. |
31 | </p> |
32 | |
33 | <p> |
34 | Iambién puedes obtener un efecto |
35 | como libro de cuentos usando |
36 | float: inline-start |
37 | dentro de p::first-letter. |
38 | </p> |
39 | |
40 | <p> |
41 | Lorem ipsum dolor sit amet |
42 | consectetur adipisicing elit. |
43 | Iure, assumenda reiciendis. |
44 | Reprehenderit non sunt enim sequi |
45 | vel consequatur nostrum suscipit, |
46 | numquam, ipsam commodi placeat |
47 | quibusdam porro excepturi |
48 | aliquid officia labore! |
49 | </p> |
50 | |
51 | <footer> |
52 | <p> |
53 | © 2025 |
54 | Gilberto Pacheco Gallegos |
55 | </p> |
56 | </footer> |
57 | |
58 | </body> |
59 | |
60 | </html> |
La propiedad float en W3 Schools: https://www.w3schools.com/css/css_float.asp
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>Columnas</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | main { |
13 | /* Intenta usar 3 columnas. */ |
14 | column-count: 3; |
15 | /* Cada columna debe tener al |
16 | * menos 200px de ancho */ |
17 | column-width: 200px; |
18 | /* 1 renglón de reparación entre |
19 | * columnas. */ |
20 | column-gap: 1rem; |
21 | /* Pone una línea sólida entre |
22 | * columnas. */ |
23 | column-rule: solid; |
24 | |
25 | } |
26 | </style> |
27 | |
28 | </head> |
29 | |
30 | <body> |
31 | |
32 | <h1>Columnas</h1> |
33 | <main> |
34 | <p> |
35 | Lorem ipsum dolor sit amet |
36 | consectetur adipisicing elit. |
37 | Iure, assumenda reiciendis. |
38 | </p> |
39 | <p> |
40 | Lorem ipsum dolor sit amet |
41 | consectetur adipisicing elit. |
42 | Iure, assumenda reiciendis. |
43 | </p> |
44 | <p> |
45 | Lorem ipsum dolor sit amet |
46 | consectetur adipisicing elit. |
47 | Iure, assumenda reiciendis. |
48 | </p> |
49 | </main> |
50 | </body> |
51 | |
52 | </html> |
Columnas en MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/columns
flex
11 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>Flex 1</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | menu { |
13 | --gap: 0.5rem; |
14 | display: flex; |
15 | /* Quita las viñetas. */ |
16 | list-style-type: none; |
17 | margin: 0; |
18 | padding: var(--gap); |
19 | /* Espacio entre elementos. */ |
20 | gap: var(--gap); |
21 | border: solid; |
22 | /* Centra verticalmente el |
23 | * contenido. */ |
24 | align-items: center; |
25 | } |
26 | |
27 | #enLinea { |
28 | display: inline-flex; |
29 | } |
30 | |
31 | .creceMargenFinal { |
32 | margin-inline-end: auto |
33 | } |
34 | </style> |
35 | |
36 | </head> |
37 | |
38 | <body> |
39 | |
40 | <h1>Flex 1</h1> |
41 | |
42 | <menu> |
43 | <li><button>≡</button></li> |
44 | <li class="creceMargenFinal"> |
45 | Ejemplo de flex |
46 | </li> |
47 | <li><button>💾</button></li> |
48 | <li><button>🗑</button></li> |
49 | </menu> |
50 | |
51 | Inicio |
52 | <menu id="enLinea"> |
53 | <li><button>≡</button></li> |
54 | <li class="creceMargenFinal"> |
55 | Ejemplo de flex |
56 | </li> |
57 | <li><button>💾</button></li> |
58 | <li><button>🗑</button></li> |
59 | </menu> |
60 | Fin |
61 | |
62 | </body> |
63 | |
64 | </html> |
El display flex en CSS Tricks: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
flex
21 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>Flex 2</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | body { |
13 | display: flex; |
14 | flex-wrap: wrap; |
15 | /* Espacio horizontal entre |
16 | * elementos. */ |
17 | row-gap: 1rem; |
18 | /* Espacio vertical entre |
19 | * elementos. */ |
20 | column-gap: 0.5rem; |
21 | } |
22 | |
23 | nav { |
24 | /* flex muestra main en el orden |
25 | * 1, o sea al inicio. */ |
26 | order: 1; |
27 | } |
28 | |
29 | main { |
30 | /* 1: Expande horizontalmente, |
31 | * 1: Contrae horizontalmente, |
32 | * 300px: Tamaño base. */ |
33 | flex: 1 1 300px; |
34 | /* flex muestra main en el orden |
35 | * 2, o sea después de nav. */ |
36 | order: 2; |
37 | } |
38 | |
39 | aside { |
40 | /* flex muestra main en el orden |
41 | * 3, o sea después de main. */ |
42 | order: 3; |
43 | } |
44 | |
45 | nav, |
46 | aside { |
47 | /* 1: Expande horizontalmente, |
48 | * 1: Contrae horizontalmente, |
49 | * 200px: Tamaño base. */ |
50 | flex: 1 1 200px |
51 | } |
52 | </style> |
53 | |
54 | </head> |
55 | |
56 | <body> |
57 | |
58 | <main> |
59 | <h1>Flex 2</h1> |
60 | <p> |
61 | Este ejemplo usa display: flex |
62 | para una página principal. |
63 | </p> |
64 | <p> |
65 | flex-wrap: wrap permite que el |
66 | contenido se parta. |
67 | </p> |
68 | <p> |
69 | Este main se puede expander, |
70 | contraer y su tamaño base es de |
71 | 300px |
72 | </p> |
73 | </main> |
74 | |
75 | <nav> |
76 | <h2>Navegación</h2> |
77 | <p> |
78 | Este nav se puede expander o |
79 | contraer si es necesario y su |
80 | tamaño base es de 200px |
81 | </p> |
82 | <p> |
83 | <a href="https://facebook.com" |
84 | target="_blank" |
85 | rel="noreferrer"> |
86 | Facebook</a> |
87 | </p> |
88 | </nav> |
89 | |
90 | <aside> |
91 | <h2>Aside</h2> |
92 | <p> |
93 | Este aside se puede expander, |
94 | contraer y su tamaño base es de |
95 | 200px |
96 | </p> |
97 | </aside> |
98 | |
99 | </body> |
100 | |
101 | </html> |
flex
31 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>Flex 3</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | body { |
13 | /* body ocupa toda la altura de |
14 | * visualización y se ajusta a |
15 | * los distintos modos del |
16 | * móvil. */ |
17 | height: 100dvh; |
18 | margin: 0 0.5rem; |
19 | display: flex; |
20 | /* El despliegue se hace |
21 | * verticalmente.*/ |
22 | flex-direction: column; |
23 | /* El despliegue se hace |
24 | * verticalmente.*/ |
25 | align-items: center; |
26 | } |
27 | |
28 | main { |
29 | /* El elemento crece si es |
30 | * necesario para llenar el |
31 | * flex. */ |
32 | flex-grow: 1; |
33 | /* El elemento se estira para |
34 | * ajustarse al ancho del |
35 | * flex.*/ |
36 | align-self: stretch; |
37 | /* Si el elemento no cabe |
38 | * completamente en el espacio |
39 | * asignado, se ponen barras de |
40 | * desplazamiento.*/ |
41 | overflow: auto; |
42 | } |
43 | |
44 | aside { |
45 | /* Evita que margin y float se |
46 | * salgan del elemento. */ |
47 | display: flow-root; |
48 | } |
49 | </style> |
50 | |
51 | </head> |
52 | |
53 | <body> |
54 | |
55 | <h1>Flex 3</h1> |
56 | |
57 | <main> |
58 | <p> |
59 | Este ejemplo usa display: flex |
60 | con orientación vertical. |
61 | </p> |
62 | <p> |
63 | Lorem ipsum dolor sit amet |
64 | consectetur adipisicing elit. |
65 | Omnis, eius. Quaerat alias |
66 | facilis recusandae, voluptate |
67 | cumque quod tenetur |
68 | necessitatibus exercitationem |
69 | beatae cupiditate iste |
70 | voluptatum, optio debitis |
71 | deserunt laboriosam placeat |
72 | odit?. |
73 | </p> |
74 | </main> |
75 | |
76 | <aside> |
77 | <p>Se feliz 😁.</p> |
78 | </aside> |
79 | |
80 | </body> |
81 | |
82 | </html> |
grid
11 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>Grid 1</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | body { |
13 | display: grid; |
14 | margin: 0 0.5rem; |
15 | height: 100dvh; |
16 | column-gap: 0.5rem; |
17 | row-gap: 1rem; |
18 | /* Declara 3 columnas: |
19 | * columna 1 20vw de amcho |
20 | * columna 2: se ajusta ancho |
21 | * columna 3: 20vw de amcho */ |
22 | grid-template-columns: 20vw 1fr 20vw; |
23 | /* Declara 3 renglones: |
24 | * remglón 1 4rem de alto |
25 | * remglón 2: se ajusta altura |
26 | * remglón 3: 4rem de alto */ |
27 | grid-template-rows: 4rem 1fr 4rem; |
28 | grid-template-areas: |
29 | "head head head" |
30 | "nav main aside" |
31 | "foot foot foot"; |
32 | } |
33 | |
34 | h1 { |
35 | margin: 0; |
36 | grid-area: head; |
37 | align-self: center; |
38 | justify-self: center |
39 | } |
40 | |
41 | main { |
42 | grid-area: main; |
43 | overflow: auto; |
44 | } |
45 | |
46 | nav { |
47 | grid-area: nav; |
48 | overflow: auto; |
49 | } |
50 | |
51 | aside { |
52 | grid-area: aside; |
53 | overflow: auto; |
54 | } |
55 | |
56 | footer { |
57 | display: flow-root; |
58 | grid-area: foot; |
59 | align-self: center; |
60 | justify-self: center |
61 | } |
62 | </style> |
63 | |
64 | </head> |
65 | |
66 | <body> |
67 | |
68 | <h1>Grid 1</h1> |
69 | |
70 | <main> |
71 | <p> |
72 | Este ejemplo usa display: grid |
73 | para una página principal. |
74 | </p> |
75 | <p> |
76 | Lorem ipsum dolor sit amet |
77 | consectetur adipisicing elit. |
78 | Omnis, eius. Quaerat alias |
79 | facilis recusandae, voluptate |
80 | cumque quod tenetur |
81 | necessitatibus exercitationem |
82 | beatae cupiditate iste |
83 | voluptatum, optio debitis |
84 | deserunt laboriosam placeat |
85 | odit?. |
86 | </p> |
87 | </main> |
88 | |
89 | <nav> |
90 | <h2>Navegación</h2> |
91 | <p> |
92 | <a href="https://facebook.com" |
93 | target="_blank" |
94 | rel="noreferrer"> |
95 | Facebook</a> |
96 | </p> |
97 | </nav> |
98 | |
99 | <aside> |
100 | <h2>Aside</h2> |
101 | <p> |
102 | Este es un aside. |
103 | </p> |
104 | </aside> |
105 | |
106 | <footer> |
107 | <p> |
108 | © 2025 |
109 | Gilberto Pacheco Gallegos |
110 | </p> |
111 | </footer> |
112 | |
113 | </body> |
114 | |
115 | </html> |
El display grid en CSS Tricks: https://css-tricks.com/snippets/css/complete-guide-grid/
grid
21 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>Grid 2</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | body { |
13 | font-family: sans-serif; |
14 | } |
15 | |
16 | ol { |
17 | list-style-type: none; |
18 | margin: 0; |
19 | padding: 0.5rem; |
20 | display: grid; |
21 | gap: 0.5rem; |
22 | grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); |
23 | } |
24 | |
25 | img { |
26 | max-width: 100%; |
27 | } |
28 | </style> |
29 | |
30 | </head> |
31 | |
32 | <body> |
33 | |
34 | <h1>Grid 2</h1> |
35 | |
36 | <nav> |
37 | <ol> |
38 | |
39 | <li> |
40 | <figure> |
41 | <img alt="Lobo" |
42 | src="https://images.pexels.com/photos/397857/pexels-photo-397857.jpeg"> |
43 | <figcaption>Lobo</figcaption> |
44 | </figure> |
45 | <p> |
46 | <a target="_blank" rel=”noreferrer” |
47 | href="https://www.pexels.com/es-es/foto/lobo-blanco-y-negro-397857/"> |
48 | Foto de Steve en Pexels.</a> |
49 | </p> |
50 | </li> |
51 | |
52 | <li> |
53 | <figure> |
54 | <img alt="Buho" |
55 | src="https://images.pexels.com/photos/3732453/pexels-photo-3732453.jpeg"> |
56 | <figcaption>Buho</figcaption> |
57 | </figure> |
58 | <p> |
59 | <a target="_blank" rel=”noreferrer” |
60 | href="https://www.pexels.com/es-es/foto/foto-de-buho-ural-3732453/"> |
61 | Foto de Erik Karits en Pexels.</a> |
62 | </p> |
63 | </li> |
64 | |
65 | <li> |
66 | <figure> |
67 | <img alt="Perro" |
68 | src="https://images.pexels.com/photos/3978352/pexels-photo-3978352.jpeg"> |
69 | <figcaption>Perro </figcaption> |
70 | </figure> |
71 | <p> |
72 | <a target="_blank" rel=”noreferrer” |
73 | href="https://www.pexels.com/es-es/foto/perro-de-pelo-corto-marron-y-blanco-acostado-3978352/"> |
74 | Foto de Creative Workshop en Pexels.</a> |
75 | </p> |
76 | </li> |
77 | |
78 | <li> |
79 | <figure> |
80 | <img alt="Gato" |
81 | src="https://images.pexels.com/photos/141496/pexels-photo-141496.jpeg"> |
82 | <figcaption>Gato</figcaption> |
83 | </figure> |
84 | <p> |
85 | <a target="_blank" rel=”noreferrer” |
86 | href="https://www.pexels.com/es-es/foto/gatito-gris-en-bolsa-de-papel-plateada-141496/"> |
87 | Foto de Vadim B en Pexels.</a> |
88 | </p> |
89 | </li> |
90 | |
91 | <li> |
92 | <figure> |
93 | <img alt="León" |
94 | src="https://images.pexels.com/photos/2270848/pexels-photo-2270848.jpeg"> |
95 | <figcaption>León</figcaption> |
96 | </figure> |
97 | <p> |
98 | <a target="_blank" rel=”noreferrer” |
99 | href="https://www.pexels.com/es-es/foto/leon-marron-2270848/"> |
100 | Foto de Ralph en Pexels.</a> |
101 | </p> |
102 | </li> |
103 | |
104 | <li> |
105 | <figure> |
106 | <img alt="Oso" |
107 | src="https://images.pexels.com/photos/35435/pexels-photo.jpg"> |
108 | <figcaption>Oso</figcaption> |
109 | </figure> |
110 | <p> |
111 | <a target="_blank" rel=”noreferrer” |
112 | href="https://www.pexels.com/es-es/foto/oso-cafe-35435/"> |
113 | Foto de Rasmus Svinding en Pexels.</a> |
114 | </p> |
115 | </li> |
116 | |
117 | <li> |
118 | <figure> |
119 | <img alt="Coyote" |
120 | src="https://images.pexels.com/photos/10226903/pexels-photo-10226903.jpeg"> |
121 | <figcaption>Coyote</figcaption> |
122 | </figure> |
123 | <p> |
124 | <a target="_blank" rel=”noreferrer” |
125 | href="https://www.pexels.com/es-es/foto/animal-perro-mono-hierba-10226903/"> |
126 | Foto de Esteban Arango en Pexels.</a> |
127 | </p> |
128 | </li> |
129 | |
130 | </ol> |
131 | </nav> |
132 | |
133 | </body> |
134 | |
135 | </html> |
@media
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>@media</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | body { |
13 | --gap: 0.5rem; |
14 | margin-top: 0; |
15 | } |
16 | |
17 | h1 { |
18 | margin: 0; |
19 | } |
20 | |
21 | menu, |
22 | header { |
23 | grid-area: head; |
24 | position: sticky; |
25 | top: 0; |
26 | display: flex; |
27 | gap: var(--gap); |
28 | align-items: center; |
29 | } |
30 | |
31 | @media screen and (max-width: 599px) { |
32 | |
33 | menu { |
34 | /* Quita las viñetas. */ |
35 | list-style-type: none; |
36 | padding: 0; |
37 | margin: 0; |
38 | } |
39 | |
40 | header { |
41 | display: none; |
42 | } |
43 | |
44 | main { |
45 | flex-grow: 1; |
46 | align-self: stretch |
47 | } |
48 | |
49 | } |
50 | |
51 | @media screen and (min-width: 600px) { |
52 | body { |
53 | display: grid; |
54 | column-gap: var(--gap); |
55 | row-gap: 1rem; |
56 | grid-template-columns: 1fr 20vw; |
57 | grid-template-rows: auto 1fr auto; |
58 | grid-template-areas: |
59 | "head head" |
60 | "main aside" |
61 | "foot foot"; |
62 | } |
63 | |
64 | menu { |
65 | display: none; |
66 | } |
67 | |
68 | header nav ul { |
69 | display: inline-flex; |
70 | list-style-type: none; |
71 | padding: 0; |
72 | margin: 0; |
73 | gap: var(--gap); |
74 | justify-content: center; |
75 | } |
76 | |
77 | header nav ul p { |
78 | margin: 0; |
79 | } |
80 | |
81 | main { |
82 | grid-area: main; |
83 | min-height: 50vh; |
84 | overflow: auto; |
85 | } |
86 | |
87 | aside { |
88 | grid-area: aside; |
89 | } |
90 | |
91 | footer { |
92 | grid-area: foot; |
93 | display: flow-root; |
94 | text-align: center; |
95 | } |
96 | |
97 | } |
98 | </style> |
99 | |
100 | </head> |
101 | |
102 | <body> |
103 | |
104 | <menu> |
105 | <li> |
106 | <button type="button" popovertarget="navGeneral">≡</button> |
107 | </li> |
108 | <li> |
109 | <h1>@media</h1> |
110 | </li> |
111 | </menu> |
112 | |
113 | <nav id="navGeneral" popover="auto"> |
114 | <h2>Enlaces externos</h2> |
115 | <ul> |
116 | <li> |
117 | <p> |
118 | <a target="_blank" rel="noreferrer" href="https://savethecat.com/"> |
119 | Salvar al gato. |
120 | </a> |
121 | </p> |
122 | </li> |
123 | <li> |
124 | <p> |
125 | <a target="_blank" rel="noreferrer" href="https://www.showrunner.xyz/"> |
126 | Showrunner |
127 | </a> |
128 | </p> |
129 | </li> |
130 | <li> |
131 | <p> |
132 | <a target="_blank" rel="noreferrer" href="https://google.com/"> |
133 | |
134 | </a> |
135 | </p> |
136 | </li> |
137 | </ul> |
138 | </nav> |
139 | |
140 | <header> |
141 | <h1>@media</h1> |
142 | <nav> |
143 | <ul> |
144 | <li> |
145 | <p> |
146 | <a target="_blank" rel="noreferrer" href="https://savethecat.com/"> |
147 | Salvar al gato. |
148 | </a> |
149 | </p> |
150 | </li> |
151 | <li> |
152 | <p> |
153 | <a target="_blank" rel="noreferrer" href="https://www.showrunner.xyz/"> |
154 | Showrunner |
155 | </a> |
156 | </p> |
157 | </li> |
158 | <li> |
159 | <p> |
160 | <a target="_blank" rel="noreferrer" href="https://google.com/"> |
161 | |
162 | </a> |
163 | </p> |
164 | </li> |
165 | </ul> |
166 | </nav> |
167 | </header> |
168 | |
169 | <main> |
170 | <p> |
171 | Este ejemplo usa @media para |
172 | seleccionar el display |
173 | de la página principal. |
174 | </p> |
175 | <p> |
176 | Lorem ipsum dolor sit amet |
177 | consectetur adipisicing elit. |
178 | Omnis, eius. Quaerat alias |
179 | facilis recusandae, voluptate |
180 | cumque quod tenetur |
181 | necessitatibus exercitationem |
182 | beatae cupiditate iste |
183 | voluptatum, optio debitis |
184 | deserunt laboriosam placeat |
185 | odit?. |
186 | </p> |
187 | |
188 | </main> |
189 | |
190 | <aside> |
191 | <h2>Aside</h2> |
192 | <p> |
193 | Este aside cambia su despliegue. |
194 | </p> |
195 | </aside> |
196 | |
197 | <footer> |
198 | <p> |
199 | © 2025 |
200 | Gilberto Pacheco Gallegos |
201 | </p> |
202 | </footer> |
203 | |
204 | </body> |
205 | |
206 | </html> |
@media en MDN: https://developer.mozilla.org/es/docs/Web/CSS/@media
@media en CSS Tricks: https://css-tricks.com/a-complete-guide-to-css-media-queries/
@container
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>@container</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | body { |
13 | margin-top: 0; |
14 | } |
15 | |
16 | h1 { |
17 | position: sticky; |
18 | top: 0; |
19 | margin: 0; |
20 | } |
21 | |
22 | html { |
23 | container-type: scroll-state; |
24 | container-name: scroller; |
25 | } |
26 | |
27 | main { |
28 | container-type: inline-size; |
29 | container-name: main; |
30 | } |
31 | |
32 | @container main (min-width: 500px) { |
33 | |
34 | p::first-letter { |
35 | font-size: 3em; |
36 | float: inline-start; |
37 | } |
38 | |
39 | p { |
40 | clear: both; |
41 | } |
42 | |
43 | } |
44 | |
45 | @container scroller scroll-state(scrollable: top) { |
46 | h1 { |
47 | border: solid; |
48 | } |
49 | } |
50 | </style> |
51 | |
52 | </head> |
53 | |
54 | <body> |
55 | |
56 | <h1>@container</h1> |
57 | |
58 | <main> |
59 | |
60 | <p> |
61 | Este ejemplo usa @container. |
62 | </p> |
63 | <p> |
64 | Lorem ipsum dolor sit amet |
65 | consectetur adipisicing elit. |
66 | Iure, assumenda reiciendis. |
67 | Reprehenderit non sunt enim |
68 | sequi vel consequatur nostrum |
69 | suscipit, numquam, ipsam commodi |
70 | placeat quibusdam porro |
71 | excepturi aliquid officia |
72 | labore! |
73 | </p> |
74 | <p> |
75 | Lorem ipsum dolor sit amet |
76 | consectetur adipisicing elit. |
77 | Iure, assumenda reiciendis. |
78 | Reprehenderit non sunt enim |
79 | sequi vel consequatur nostrum |
80 | suscipit, numquam, ipsam commodi |
81 | placeat quibusdam porro |
82 | excepturi aliquid officia |
83 | labore! |
84 | </p> |
85 | |
86 | </main> |
87 | |
88 | </body> |
89 | |
90 | </html> |
CSS container queries en MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment/Container_queries
Using container scroll-state queries en MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_conditional_rules/Container_scroll-state_queries
color-scheme
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>color-scheme</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | html { |
13 | color-scheme: light dark; |
14 | } |
15 | |
16 | @media (prefers-color-scheme: light) { |
17 | html { |
18 | --color: yellow; |
19 | --backgroundColor: blue; |
20 | } |
21 | } |
22 | |
23 | @media (prefers-color-scheme: dark) { |
24 | html { |
25 | --color: blue; |
26 | --backgroundColor: yellow; |
27 | } |
28 | } |
29 | |
30 | h1 { |
31 | color: var(--color); |
32 | background-color: var(--backgroundColor); |
33 | } |
34 | </style> |
35 | |
36 | </head> |
37 | |
38 | <body> |
39 | |
40 | <h1>color-scheme</h1> |
41 | |
42 | <p> |
43 | Este ejemplo usa color-scheme. |
44 | </p> |
45 | |
46 | </body> |
47 | |
48 | </html> |
color-scheme en MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme
color-scheme
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>color-scheme</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | html { |
13 | color-scheme: light dark; |
14 | } |
15 | |
16 | @media (prefers-color-scheme: light) { |
17 | html { |
18 | --color: yellow; |
19 | --backgroundColor: blue; |
20 | } |
21 | } |
22 | |
23 | @media (prefers-color-scheme: dark) { |
24 | html { |
25 | --color: blue; |
26 | --backgroundColor: yellow; |
27 | } |
28 | } |
29 | |
30 | h1 { |
31 | color: var(--color); |
32 | background-color: var(--backgroundColor); |
33 | } |
34 | </style> |
35 | |
36 | </head> |
37 | |
38 | <body> |
39 | |
40 | <h1>color-scheme</h1> |
41 | |
42 | <p> |
43 | Este ejemplo usa color-scheme. |
44 | </p> |
45 | |
46 | </body> |
47 | |
48 | </html> |
color-scheme en MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>Web fonts</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <link rel="preconnect" href="https://fonts.googleapis.com"> |
12 | <link rel="preconnect" href="https://fonts.gstatic.com" |
13 | crossorigin> |
14 | <link |
15 | href="https://fonts.googleapis.com/css2?family=Forum&family=Winky+Rough:ital,wght@0,300..900;1,300..900&display=swap" |
16 | rel="stylesheet"> |
17 | |
18 | <style> |
19 | h1 { |
20 | font-family: "Winky Rough", sans-serif; |
21 | } |
22 | |
23 | p { |
24 | font-family: "Forum", serif; |
25 | } |
26 | </style> |
27 | |
28 | </head> |
29 | |
30 | <body> |
31 | |
32 | <h1>Web fonts</h1> |
33 | |
34 | <p> |
35 | Este ejemplo usa Web fonts. |
36 | </p> |
37 | |
38 | </body> |
39 | |
40 | </html> |
Google fonts: https://fonts.google.com/
En esta lección se mostró como implementar responsividad de las sifuientes maneras:
float
Columnas
flex
grid
@media
@container
color-scheme
Web fonts
En esta lección se presentan algunos elementos para el manejo de multimedia.
Hay varios tipos de elementos especializados en mostrar imágenes.
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.
figure
Es un elemento de agrupamiento específicamente diseñado para mostrar imágenes.
figcaption
Es un elemento de agrupamiento específicamente diseñado para mostrar el
texto que describe el contenido de un
figure
.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>Imágenes</title> |
8 | </head> |
9 | <body> |
10 | <h1>Imágenes</h1> |
11 | <style> |
12 | img { |
13 | max-width: 100% |
14 | } |
15 | </style> |
16 | <figure> |
17 | <img alt="Un gatito" |
18 | src="https://media.giphy.com/media/MDJ9IbxxvDUQM/giphy.gif"> |
19 | <figcaption>Gatito</figcaption> |
20 | </figure> |
21 | <footer> |
22 | <p> |
23 | Imágen de |
24 | <a target="_blank" rel="noreferrer" href="https://giphy.com">Giphy</a>. |
25 | </p> |
26 | </footer> |
27 | </body> |
28 | </html> |
La especificación técnica del elemento
img
está en
https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element
La especificación técnica del elemento
figure
está en
https://html.spec.whatwg.org/multipage/grouping-content.html#the-figure-element
La especificación técnica del elemento
figcaption
está en
https://html.spec.whatwg.org/multipage/grouping-content.html#the-figcaption-element
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.
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.
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
.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" |
6 | content="width=device-width"> |
7 | <title>Imágenes</title> |
8 | </head> |
9 | <body> |
10 | <h1>Imágenes</h1> |
11 | <style> |
12 | img { |
13 | max-width: 100% |
14 | } |
15 | </style> |
16 | <figure> |
17 | <img alt="Un gatito" |
18 | src="https://media.giphy.com/media/MDJ9IbxxvDUQM/giphy.gif"> |
19 | <figcaption>Gatito</figcaption> |
20 | </figure> |
21 | <footer> |
22 | <p> |
23 | Imágen de |
24 | <a target="_blank" rel="noreferrer" href="https://giphy.com">Giphy</a>. |
25 | </p> |
26 | </footer> |
27 | </body> |
28 | </html> |
La especificación técnica del elemento
audio
está en
https://html.spec.whatwg.org/multipage/media.html#the-audio-element
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.
poster
Proporciona la URL de una imagen que se muestra mientras no se haya cargado ningún byte del video.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Video</title> |
9 | <style> |
10 | video { |
11 | max-width: 100% |
12 | } |
13 | </style> |
14 | </head> |
15 | |
16 | <body> |
17 | <h1>Video</h1> |
18 | <figure> |
19 | <video autoplay loop |
20 | src="https://media.giphy.com/media/1W62t8wP8m1iM/giphy.mp4"> |
21 | Tu navegador no soporta video. |
22 | Usa el siguiente enlace |
23 | <a target="_blank" rel="noreferrer" |
24 | href="https://media.giphy.com/media/1W62t8wP8m1iM/giphy.mp4">Para abrir el |
25 | video</a> |
26 | </video> |
27 | </figure> |
28 | <footer> |
29 | <p> |
30 | Video de |
31 | <a target="_blank" rel="noreferrer" |
32 | href="https://giphy.com">Giphy</a>. |
33 | </p> |
34 | </footer> |
35 | </body> |
36 | |
37 | </html> |
La especificación técnica del elemento
video
está en
https://html.spec.whatwg.org/multipage/media.html#the-video-element
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Fondo</title> |
9 | <style> |
10 | html { |
11 | /* Como el fondo es oscuro, se |
12 | * escoje un color de letra que |
13 | * no se pierda. */ |
14 | color: white; |
15 | /* URL de la imagen de fondo. En |
16 | * este caso está hospedada en |
17 | * "giphy.com". */ |
18 | background-image: |
19 | url(https://media.giphy.com/media/3oKIPhf02cXU9W4Le0/giphy.gif); |
20 | /* La imagen de fondo no se |
21 | * repite en caso de que sea más |
22 | * pequeña que el elemento en |
23 | * que se coloca. En este caso |
24 | * html es la ventana. */ |
25 | background-repeat: no-repeat; |
26 | /* La imagen de fondo se muestra |
27 | * centrada horizontalmente. */ |
28 | background-position-x: |
29 | center; |
30 | /* La imagen de fondo se muestra |
31 | * centrada verticalmente. */ |
32 | background-position-y: |
33 | center; |
34 | /* La imagen de fondo se muestra |
35 | * fija y no se desplaza. */ |
36 | background-attachment: |
37 | fixed; |
38 | /* Distintas propiedades para |
39 | * distintos navegadores |
40 | * indicando que la imagen de |
41 | * fondo tiene un tamaño que |
42 | * cubre toda la ventana. */ |
43 | -webkit-background-size: cover; |
44 | -moz-background-size: cover; |
45 | -o-background-size: cover; |
46 | background-size: cover; |
47 | } |
48 | |
49 | /* Estilo para las anclas o |
50 | * hipervínculos. */ |
51 | a { |
52 | /* Como el fondo es oscuro, se |
53 | * escoje un color de letra que |
54 | * no se pierda y se distinga |
55 | * del resto del texto. */ |
56 | color: yellow; |
57 | } |
58 | </style> |
59 | </head> |
60 | |
61 | <body> |
62 | <h1>Fondo</h1> |
63 | <p> |
64 | Este ejemplo te muestra como |
65 | poner fondo a una página. |
66 | </p> |
67 | <footer> |
68 | <p> |
69 | © 2022 |
70 | Gilberto Pacheco Gallegos. |
71 | </p> |
72 | <p> |
73 | Imagen de |
74 | <a href="https://giphy.com"> |
75 | https://giphy.com</a>. |
76 | </p> |
77 | </footer> |
78 | </body> |
79 | |
80 | </html> |
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.
En esta lección se presentan algunos elementos para elaborar formularios.
A partir de esta lección 11 se requiere que uses el contenido de https://gilpgijs.github.io y https://gilpgpoojs.github.io.
Este es un ejemplo típico de un formulario HTML.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | |
6 | <meta charset="UTF-8"> |
7 | <title>Formulario</title> |
8 | <meta name="viewport" |
9 | content="width=device-width"> |
10 | |
11 | <style> |
12 | body { |
13 | font-family: sans-serif; |
14 | } |
15 | |
16 | form { |
17 | max-width: 900px; |
18 | margin-inline: auto; |
19 | } |
20 | |
21 | label, |
22 | legend { |
23 | font-weight: bold; |
24 | } |
25 | |
26 | fieldset label { |
27 | font-weight: normal; |
28 | } |
29 | |
30 | label:has(:not([type="radio"]):required)::before { |
31 | content: "✳ "; |
32 | } |
33 | |
34 | label:has(:not([type="radio"]):invalid)::before { |
35 | content: "❌ "; |
36 | } |
37 | |
38 | label:has(:not([type="radio"]):invalid:required)::before { |
39 | content: "✳ ❌ "; |
40 | } |
41 | |
42 | label output, |
43 | label input:not([type="checkbox"], [type="radio"], [type="range"]), |
44 | label select, |
45 | label textarea { |
46 | display: block; |
47 | box-sizing: border-box; |
48 | width: 100%; |
49 | } |
50 | |
51 | label:has([type="range"]) { |
52 | white-space: pre-wrap; |
53 | } |
54 | |
55 | fieldset { |
56 | box-sizing: border-box; |
57 | } |
58 | |
59 | fieldset p { |
60 | margin-block: 0.5rem; |
61 | } |
62 | |
63 | fieldset label:has(:invalid)::after { |
64 | content: "❌"; |
65 | } |
66 | |
67 | legend:has(~p :required)::before { |
68 | content: "✳ "; |
69 | } |
70 | |
71 | input[name="temperatura2"] { |
72 | writing-mode: vertical-lr; |
73 | } |
74 | </style> |
75 | |
76 | </head> |
77 | |
78 | <body> |
79 | |
80 | <form id="forma"> |
81 | |
82 | <h1>Formulario</h1> |
83 | |
84 | <p> |
85 | <label> |
86 | Nombre |
87 | <output name="nombre">Pp</output> |
88 | </label> |
89 | </p> |
90 | |
91 | <p> |
92 | <label accesskey="A"> |
93 | Apellidos |
94 | <input name="apellidos" type="text" placeholder="ej. Pérez López" |
95 | required> |
96 | <small>Los apellidos de tu familia</small> |
97 | </label> |
98 | </p> |
99 | |
100 | <input name="clave" type="hidden" value=""> |
101 | |
102 | <p> |
103 | <label> |
104 | Restaurante favorito |
105 | <input name="apellidos" type="text" value="La cabaña del Tio Jese"> |
106 | </label> |
107 | </p> |
108 | |
109 | <p> |
110 | <label> |
111 | Número telefónico |
112 | <input name="telefono" type="tel"> |
113 | </label> |
114 | </p> |
115 | |
116 | <p> |
117 | <label> |
118 | Número de tarjeta |
119 | <input name="tarjeta" type="text" pattern="\d{14,19}" inputmode="numeric"> |
120 | <small>14 a 19 letras o caracteres.</small> |
121 | </label> |
122 | </p> |
123 | |
124 | <p> |
125 | <label> |
126 | Sitio personal |
127 | <input name="sitio" type="url" list="sitios"> |
128 | </label> |
129 | </p> |
130 | <datalist id="sitios"> |
131 | <option>https://facebook.com</option> |
132 | <option>https://google.com</option> |
133 | <option>https://tiktok.com</option> |
134 | <option>https://youtube.com</option> |
135 | </datalist> |
136 | <p> |
137 | <label> |
138 | Email para quejas |
139 | <input name="quejas" type="email"> |
140 | </label> |
141 | </p> |
142 | |
143 | <p> |
144 | <label> |
145 | Match |
146 | <input name="match" type="password" required pattern="\w{4,7}"> |
147 | </label> |
148 | <small>4 a 7 letras o caracteres.</small> |
149 | </p> |
150 | |
151 | <p> |
152 | <label> |
153 | Próximo día festivo |
154 | <input name="proximo" type="date"> |
155 | </label> |
156 | </p> |
157 | |
158 | <p> |
159 | <label> |
160 | Próximo día libre |
161 | <input name="libre" type="date" value="2025-02-14" min="2025-01-01" |
162 | max="2025-06-01" step="2"> |
163 | </label> |
164 | </p> |
165 | |
166 | <p> |
167 | <label> |
168 | Mes |
169 | <input name="mes" type="month" value="2025-04" min="2025-01" max="2025-12" |
170 | step="3"> |
171 | </label> |
172 | </p> |
173 | |
174 | <p> |
175 | <label> |
176 | Semana de vacaciones |
177 | <input name="vacaciones" type="week" value="2025-W05" min="2025-W01" |
178 | max="2025-W54" step="2"> |
179 | </label> |
180 | </p> |
181 | |
182 | <p> |
183 | <label> |
184 | Hora de la reunión |
185 | <input name="horaReunion" type="time" value="15:30" min="07:00" |
186 | max="17:30" step="1800"> |
187 | </label> |
188 | </p> |
189 | |
190 | <p> |
191 | <label> |
192 | Fecha y hora local |
193 | <input name="nacimiento" type="datetime-local" value="2025-03-18T15:00" |
194 | min="2025-01-01T10:00" max="2025-12-31T22:00" step="3600"> |
195 | </label> |
196 | </p> |
197 | |
198 | <p> |
199 | <label> |
200 | Altura |
201 | <input name="altura" type="number" min="0.5" max="3.0" step="0.01"> |
202 | </label> |
203 | </p> |
204 | |
205 | <p> |
206 | <label> |
207 | Temperatura |
208 | -50 <input name="temperatura" type="range" min="-50" max="80" step="10" |
209 | value="20"> 80</label> |
210 | </p> |
211 | |
212 | <p> |
213 | <label> |
214 | Temperatura 2 |
215 | -50 |
216 | <input name="temperatura2" type="range" min="-50" max="80" |
217 | value="20" list="temperaturas"> |
218 | 80</label> |
219 | </p> |
220 | <datalist id="temperaturas"> |
221 | <option value="-50">Congelado</option> |
222 | <option value="-30"></option> |
223 | <option value="0"></option> |
224 | <option value="30"></option> |
225 | <option value="50"></option> |
226 | <option value="80">Quemándose</option> |
227 | </datalist> |
228 | <p> |
229 | <label> |
230 | Color |
231 | <input name="color" type="color" colorspace="limited-srgb" value="#00ff00"> |
232 | </label> |
233 | </p> |
234 | |
235 | <p> |
236 | <label> |
237 | Tarea |
238 | <input name="tarea" type="file" accept="image/*,application/pdf"> |
239 | </label> |
240 | </p> |
241 | |
242 | <p> |
243 | <label> |
244 | <input name="aprobado" type="checkbox"> |
245 | Aprobado |
246 | </label> |
247 | </p> |
248 | |
249 | <fieldset> |
250 | <legend>Pasatiempos</legend> |
251 | <p> |
252 | <label> |
253 | <input type="checkbox" name="pasatiempos[]" value="fut"> |
254 | Futbol |
255 | </label> |
256 | </p> |
257 | <p> |
258 | <label> |
259 | <input type="checkbox" name="pasatiempos[]" value="chess" checked> |
260 | Ajedrez |
261 | </label> |
262 | </p> |
263 | <p> |
264 | <label> |
265 | <input type="checkbox" name="pasatiempos[]" value="basket" checked> |
266 | Basketbol |
267 | </label> |
268 | </p> |
269 | </fieldset> |
270 | |
271 | <fieldset> |
272 | <legend>Madrugador</legend> |
273 | <p> |
274 | <label><input type="radio" name="madrugador" value="si" checked>Si</label> |
275 | <label><input type="radio" name="madrugador" value="no">No</label> |
276 | </p> |
277 | </fieldset> |
278 | |
279 | <fieldset> |
280 | <legend>Tamaño</legend> |
281 | <p> |
282 | <label> |
283 | <input type="radio" name="tamano" value="grande" required> |
284 | Grande |
285 | </label> |
286 | </p> |
287 | <p> |
288 | <label> |
289 | <input type="radio" name="tamano" value="mediano"> |
290 | Mediano |
291 | </label> |
292 | </p> |
293 | <p> |
294 | <label> |
295 | <input type="radio" name="tamano" value="chico"> |
296 | Chico |
297 | </label> |
298 | </p> |
299 | </fieldset> |
300 | |
301 | <p> |
302 | <label> |
303 | Género Musical |
304 | <select name="generoMusical" required> |
305 | <option value="">Sin selección</option> |
306 | <option value="pop">Pop</option> |
307 | <option value="reg">Reguetón</option> |
308 | </select> |
309 | </label> |
310 | </p> |
311 | |
312 | <p> |
313 | <label> |
314 | Géneración |
315 | <select name="generacion" value="Z"> |
316 | <option value="boom">Baby Boom</option> |
317 | <option value="X">X</option> |
318 | <option value="">Sin selección</option> |
319 | <option value="Y">Millenoals</option> |
320 | <option value="Z">Z</option> |
321 | <option value="alfa">Alfa</option> |
322 | </select> |
323 | </label> |
324 | </p> |
325 | |
326 | <p> |
327 | <label> |
328 | Género |
329 | <select name="genero"> |
330 | <option value="masculino">Masculino</option> |
331 | <option value="femenino" selected>Femenino</option> |
332 | <option value="">-- Seleccionar --</option> |
333 | <optgroup label="Otros"> |
334 | <option value="nodecir">Prefiero no decirlo</option> |
335 | <option value="nobinario">No binario</option> |
336 | </optgroup> |
337 | </select> |
338 | </label> |
339 | </p> |
340 | |
341 | <p> |
342 | <label> |
343 | Bebidas |
344 | <select name="bebidas[]" multiple size="3"> |
345 | <option value="cafe" selected>Café</option> |
346 | <option value="agua" selected>Agua</option> |
347 | <option value="limonada">Limonada</option> |
348 | </select> |
349 | </label> |
350 | </p> |
351 | |
352 | <p> |
353 | <label> |
354 | Mi camino desde casa |
355 | <textarea name="camino" required rows="10" cols="25"></textarea> |
356 | </label> |
357 | </p> |
358 | |
359 | <p> |
360 | <label> |
361 | Mi opinión sobre la comida mexicana |
362 | <textarea name="opinion" rows="10" cols="25">Es muy rica</textarea> |
363 | </label> |
364 | </p> |
365 | |
366 | <p><small>✳ Obligatorio</small></p> |
367 | |
368 | <p> |
369 | <button type="submit">Procesar</button> |
370 | <button type="reset">Reiniciar</button> |
371 | </p> |
372 | |
373 | </form> |
374 | |
375 | </body> |
376 | |
377 | </html> |
Formularios en https://html.spec.whatwg.org/multipage/forms.html#forms
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Saludo</title> |
9 | </head> |
10 | |
11 | <body> |
12 | <!-- |
13 | form |
14 | Captura los datos para un |
15 | cálculo. |
16 | action="javascript:calcula()" |
17 | Al activar la forma, se ejecuta |
18 | la función |
19 | calcula() |
20 | de la etiqueta |
21 | <script> |
22 | que aparece más abajo. --> |
23 | <form |
24 | action="javascript:calcula()"> |
25 | <h1>Saludo</h1> |
26 | <!-- |
27 | Los elementos de captura se |
28 | pueden colocan cada uno en un |
29 | <p> --> |
30 | <p> |
31 | <!-- |
32 | label |
33 | Pone el rótulo |
34 | Nombre |
35 | que aparece más abajo, al |
36 | elemento |
37 | input |
38 | que también aparece más abajo. |
39 | --> |
40 | <label> |
41 | Nombre |
42 | <!-- |
43 | input |
44 | Campo de captura. Activa la |
45 | forma al teclear |
46 | «intro» |
47 | cuando tiene el cursor. |
48 | type="text" |
49 | Captura texto |
50 | id="inNombre" |
51 | Identificador del campo de |
52 | captura. Se puede usar desde |
53 | el elemento |
54 | <script> |
55 | más abajo. |
56 | required |
57 | Este campo no se puede quedar |
58 | en blanco. --> |
59 | <input type="text" |
60 | id="inNombre" required> |
61 | </label> |
62 | </p> |
63 | <p> |
64 | <!-- |
65 | button |
66 | Activa la forma al hacerle |
67 | click o presionado la tecla |
68 | espacio cuando tiene el |
69 | tabulador. --> |
70 | <button>Calcular</button> |
71 | </p> |
72 | </form> |
73 | <script> |
74 | /** |
75 | * Función que realiza el cálculo |
76 | * cuando se activa la forma. |
77 | */ |
78 | function calcula() { |
79 | /* Recupera el texto capturado |
80 | * en "inNombre" y lo asigna |
81 | * a la constante "nombre". */ |
82 | const nombre = inNombre.value |
83 | const saludo = saluda(nombre) |
84 | /* Despliega el saludo en un |
85 | * cuadro de diálogo. */ |
86 | alert(saludo); |
87 | } |
88 | |
89 | /** |
90 | * Función que realiza la lógica |
91 | * del cálculo. |
92 | * @param {string} nombre |
93 | */ |
94 | function saluda(nombre) { |
95 | return `Hola ${nombre}.` |
96 | } |
97 | </script> |
98 | </body> |
99 | |
100 | </html> |
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.
La especificación técnica del elemento
form
está en
https://html.spec.whatwg.org/multipage/forms.html#the-form-element
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.
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.
La especificación técnica del elemento
label
está en
https://html.spec.whatwg.org/multipage/forms.html#the-label-element
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
.
La especificación técnica del elemento
button
está en
https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element
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.
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.
La especificación técnica del elemento
input
está en
https://html.spec.whatwg.org/multipage/input.html#the-input-element
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
.
La especificación técnica del elemento
output
está en
https://html.spec.whatwg.org/multipage/form-elements.html#the-output-element
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>División</title> |
9 | </head> |
10 | |
11 | <body> |
12 | <form |
13 | action="javascript:procesa()"> |
14 | <h1>División</h1> |
15 | <p> |
16 | <label> |
17 | a |
18 | <input id="inA" |
19 | type="number" |
20 | step="0.1" |
21 | required> |
22 | </label> |
23 | </p> |
24 | <p> |
25 | <label> |
26 | b |
27 | <input id="inB" |
28 | type="number" |
29 | step="0.1" |
30 | required |
31 | oninput="validaB()"> |
32 | </label> |
33 | </p> |
34 | <p> |
35 | <button>Dividir</button> |
36 | </p> |
37 | </form> |
38 | <script> |
39 | const NO_0 = "No puede ser 0" |
40 | |
41 | function validaB() { |
42 | const b = inB.valueAsNumber |
43 | /* Debe cumplirse que b |
44 | * sea un número diferente |
45 | * de 0. */ |
46 | if (isNaN(b) || b !== 0) { |
47 | inB.setCustomValidity("") |
48 | } else { |
49 | inB.setCustomValidity(NO_0) |
50 | } |
51 | } |
52 | |
53 | function procesa() { |
54 | const a = inA.valueAsNumber |
55 | const b = inB.valueAsNumber |
56 | const resultado = divide(a, b) |
57 | alert( |
58 | `${a} / ${b} = ${resultado}`) |
59 | } |
60 | |
61 | /** |
62 | * @param {number} a |
63 | * @param {number} b |
64 | */ |
65 | function divide(a, b) { |
66 | return a / b |
67 | } |
68 | </script> |
69 | </body> |
70 | |
71 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title> |
9 | Formulario con 2 botones |
10 | </title> |
11 | </head> |
12 | |
13 | <body> |
14 | <form |
15 | action=javascript:procSuma()> |
16 | <h1> |
17 | Formulario con 2 botones |
18 | </h1> |
19 | <p> |
20 | <label> |
21 | a |
22 | <input id=inA type=number |
23 | required min="0.1" max="100" |
24 | step="0.1"> |
25 | </label> |
26 | </p> |
27 | <p> |
28 | <label> |
29 | b |
30 | <input id=inB type=number |
31 | required min="0.1" max="100" |
32 | step="0.1"> |
33 | </label> |
34 | </p> |
35 | <p> |
36 | <button>Sumar</button> |
37 | <button formaction="javascript: |
38 | procResta()"> |
39 | Restar |
40 | </button> |
41 | </p> |
42 | </form> |
43 | <script> |
44 | function procSuma() { |
45 | const a = inA.valueAsNumber |
46 | const b = inB.valueAsNumber |
47 | const resultado = suma(a, b) |
48 | alert( |
49 | `${a} + ${b} = ${resultado}`) |
50 | } |
51 | |
52 | function procResta() { |
53 | const a = inA.valueAsNumber |
54 | const b = inB.valueAsNumber |
55 | const resultado = resta(a, b) |
56 | alert( |
57 | `${a} - ${b} = ${resultado}`) |
58 | } |
59 | |
60 | function suma(a, b) { |
61 | return a + b |
62 | } |
63 | |
64 | function resta(a, b) { |
65 | return a - b |
66 | } |
67 | </script> |
68 | </body> |
69 | |
70 | </html> |
El siguiente orograma usa el tipo de elemento
select
.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Recomendaciones</title> |
9 | </head> |
10 | |
11 | <body> |
12 | <form |
13 | action="javascript:procesa()"> |
14 | <h1>Recomendaciones</h1> |
15 | <p> |
16 | <label> |
17 | Género |
18 | <select id="inGenero" required> |
19 | <option value=""> |
20 | -- Selecciona -- |
21 | </option> |
22 | <option value="pop"> |
23 | Pop |
24 | </option> |
25 | <option value="reg"> |
26 | Reguetón |
27 | </option> |
28 | </select> |
29 | </label> |
30 | </p> |
31 | <p> |
32 | <button>Recomendar</button> |
33 | </p> |
34 | </form> |
35 | <script> |
36 | function procesa() { |
37 | const genero = inGenero.value |
38 | const resultado = |
39 | recomienda(genero) |
40 | alert(resultado) |
41 | } |
42 | |
43 | /** @param {string} genero */ |
44 | function recomienda(genero) { |
45 | if (genero === "pop") { |
46 | return "Para el pop te " + |
47 | "recomiendo a Dua Lipa." |
48 | } else if (genero === "reg") { |
49 | return "Para el reguetón te " + |
50 | "recomiendo a Bad Bunny." |
51 | } |
52 | } |
53 | </script> |
54 | </body> |
55 | |
56 | </html> |
La especificación técnica del elemento
select
está en
https://html.spec.whatwg.org/multipage/form-elements.html#the-select-element
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Adivina</title> |
9 | <style> |
10 | html { |
11 | font-family: sans-serif; |
12 | text-align: center; |
13 | } |
14 | |
15 | img { |
16 | max-height: 40vh; |
17 | max-width: 100%; |
18 | } |
19 | </style> |
20 | </head> |
21 | |
22 | <body> |
23 | <h1>Adivina</h1> |
24 | <figure> |
25 | <img src="https://media.giphy.com/media/JKNn9A98JBVlu/giphy.gif" |
26 | alt="Imagen de un animal"> |
27 | <figcaption> |
28 | ¿Qúe animal es este? |
29 | </figcaption> |
30 | </figure> |
31 | <p> |
32 | <button onclick="rana()"> |
33 | Una Rana |
34 | </button> |
35 | <button onclick="oso()"> |
36 | Un Oso |
37 | </button> |
38 | </p> |
39 | <script> |
40 | function rana() { |
41 | alert( |
42 | "Claro que no es una rana.") |
43 | } |
44 | |
45 | function oso() { |
46 | alert("Claro que si es un oso.") |
47 | } |
48 | </script> |
49 | </body> |
50 | |
51 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>¿Cuál te gusta más?</title> |
9 | <style> |
10 | html { |
11 | font-family: sans-serif; |
12 | } |
13 | |
14 | body { |
15 | display: grid; |
16 | gap: 0.5rem; |
17 | margin: 0; |
18 | padding: 0.5rem; |
19 | max-height: 100vh; |
20 | overflow: hidden; |
21 | grid-template-columns: |
22 | 1fr 1fr 1fr 1fr; |
23 | grid-template-areas: |
24 | "h1 h1 h1 h1" |
25 | "outGatito btnGatito outPerrito btnPerrito" |
26 | "imgGatito imgGatito imgPerrito imgPerrito"; |
27 | } |
28 | |
29 | h1 { |
30 | grid-area: h1; |
31 | text-align: center; |
32 | } |
33 | |
34 | #outGatito { |
35 | grid-area: outGatito; |
36 | justify-self: center; |
37 | } |
38 | |
39 | #btnGatito { |
40 | grid-area: btnGatito; |
41 | } |
42 | |
43 | #imgGatito { |
44 | grid-area: imgGatito; |
45 | width: 100%; |
46 | } |
47 | |
48 | #outPerrito { |
49 | grid-area: outPerrito; |
50 | justify-self: center; |
51 | } |
52 | |
53 | #btnPerrito { |
54 | grid-area: btnPerrito; |
55 | } |
56 | |
57 | #imgPerrito { |
58 | grid-area: imgPerrito; |
59 | width: 100%; |
60 | } |
61 | </style> |
62 | </head> |
63 | |
64 | <body> |
65 | <h1>¿Cuál te gusta más?</h1> |
66 | <output id="outGatito"> |
67 | 0 votos |
68 | </output> |
69 | <button id="btnGatito" |
70 | onclick="gatito()"> |
71 | Vota |
72 | </button> |
73 | <img id="imgGatito" alt="Gatito" |
74 | src="https://media.giphy.com/media/uWYjSbkIE2XIMIc7gh/giphy.gif"> |
75 | <output id=outPerrito> |
76 | 0 votos |
77 | </output> |
78 | <button id="btnPerrito" |
79 | onclick=perrito()> |
80 | Vota |
81 | </button> |
82 | <img id="imgPerrito" |
83 | alt="Perrito" |
84 | src="https://media.giphy.com/media/rXzOY4RpSA0Ug/giphy.gif"> |
85 | <script> |
86 | let votosGatito = 0 |
87 | let votosPerrito = 0 |
88 | |
89 | function gatito() { |
90 | votosGatito++ |
91 | outGatito.value = |
92 | `${votosGatito} votos` |
93 | } |
94 | |
95 | function perrito() { |
96 | votosPerrito++ |
97 | outPerrito.value = |
98 | `${votosPerrito} votos` |
99 | } |
100 | </script> |
101 | </body> |
102 | |
103 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="utf-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Recomienda</title> |
9 | <style> |
10 | html { |
11 | font-family: sans-serif; |
12 | } |
13 | |
14 | body { |
15 | display: grid; |
16 | gap: 0.5rem; |
17 | margin: 0; |
18 | padding: 0.5rem; |
19 | max-height: 100vh; |
20 | grid-template-columns: |
21 | 8rem 2fr; |
22 | grid-template-areas: |
23 | "h1 h1" |
24 | "ul section"; |
25 | } |
26 | |
27 | h1 { |
28 | grid-area: h1; |
29 | text-align: center; |
30 | } |
31 | |
32 | ul { |
33 | grid-area: ul; |
34 | } |
35 | |
36 | section { |
37 | grid-area: section; |
38 | } |
39 | |
40 | figure { |
41 | display: none; |
42 | flex: 1; |
43 | margin: 0; |
44 | width: 100%; |
45 | } |
46 | |
47 | figure:target { |
48 | display: block; |
49 | } |
50 | |
51 | img { |
52 | flex: 1; |
53 | width: 100%; |
54 | } |
55 | </style> |
56 | </head> |
57 | |
58 | <body> |
59 | <h1>Recomienda</h1> |
60 | <ul> |
61 | <li> |
62 | <p> |
63 | <a href="#pop">Pop</a> |
64 | </p> |
65 | </li> |
66 | <li> |
67 | <p> |
68 | <a href="#reg">Reguetón</a> |
69 | </p> |
70 | </li> |
71 | </ul> |
72 | <section> |
73 | <figure id="pop"> |
74 | <figcaption> |
75 | Para el pop te recomiendo a |
76 | Dua Lipa. |
77 | </figcaption> |
78 | <img alt="Gif de Dua Lipa" |
79 | src="https://media.giphy.com/media/3o7WIQin38ZjlwiKOs/giphy.gif"> |
80 | </figure> |
81 | <figure id="reg"> |
82 | <figcaption> |
83 | Para el reguetón te recomiendo |
84 | a Bad Bunny. |
85 | </figcaption> |
86 | <img alt="Gif de Bad Bunny" |
87 | src="https://media.giphy.com/media/kfcsiSjQUyMvEZ1khq/giphy.gif"> |
88 | </figure> |
89 | </section> |
90 | </body> |
91 | |
92 | </html> |
En esta lección se revisaron los elementos para elaborar formularios y se presentaron algunos ejemplos.
En esta lección se presentan los custom elements.
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:
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Custom elements</title> |
9 | <style> |
10 | elemento-1 { |
11 | color: blue; |
12 | } |
13 | |
14 | elemento-2 { |
15 | display: block; |
16 | background-color: aqua; |
17 | } |
18 | </style> |
19 | </head> |
20 | |
21 | <body> |
22 | <h1>Custom elements</h1> |
23 | <elemento-1>Hola</elemento-1> |
24 | <elemento-1> |
25 | <em>Saludos</em> |
26 | </elemento-1> |
27 | <elemento-2> |
28 | Estoy de buenas 😁 |
29 | </elemento-2> |
30 | </body> |
31 | |
32 | </html> |
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.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Acción</title> |
9 | <script> |
10 | class Elemento3 |
11 | extends HTMLElement { |
12 | connectedCallback() { |
13 | this.innerHTML = /* html */ |
14 | `Estoy volando🚁 |
15 | <strong> |
16 | alto |
17 | </strong>.` |
18 | this.addEventListener("click", |
19 | () => this.clic()) |
20 | } |
21 | clic() { |
22 | alert("ouch") |
23 | } |
24 | } |
25 | customElements.define( |
26 | "elemento-3", Elemento3) |
27 | </script> |
28 | <style> |
29 | elemento-3 { |
30 | cursor: pointer; |
31 | } |
32 | </style> |
33 | </head> |
34 | |
35 | <body> |
36 | <h1>Acción</h1> |
37 | <elemento-3></elemento-3> |
38 | <p>Saludos desde la tierra.</p> |
39 | <elemento-3></elemento-3> |
40 | </body> |
41 | |
42 | </html> |
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)
.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Atributos</title> |
9 | <script> |
10 | class MiSaludo |
11 | extends HTMLElement { |
12 | connectedCallback() { |
13 | const nombre = |
14 | this.getAttribute("nombre") |
15 | const alegre = |
16 | this.hasAttribute("alegre") |
17 | const icono = |
18 | alegre ? "😄" : "🖐" |
19 | this.innerHTML = /* html */ |
20 | `${icono} |
21 | hola |
22 | <strong>${nombre}</strong>.` |
23 | } |
24 | } |
25 | customElements.define( |
26 | "mi-saludo", MiSaludo) |
27 | </script> |
28 | </head> |
29 | |
30 | <body> |
31 | <h1>Atributos</h1> |
32 | <p> |
33 | <mi-saludo nombre="pp"> |
34 | </mi-saludo> |
35 | </p> |
36 | <p> |
37 | <mi-saludo nombre="tt" alegre> |
38 | </mi-saludo> |
39 | </p> |
40 | </body> |
41 | |
42 | </html> |
En esta lección se revisó el uso básico de los custom element.
En esta lección se presentan técnicas para elaborar juegos.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Sprite</title> |
9 | <style> |
10 | .sprite { |
11 | position: fixed; |
12 | font-size: 3rem; |
13 | } |
14 | </style> |
15 | </head> |
16 | |
17 | <body> |
18 | <h1>Sprite</h1> |
19 | <p> |
20 | Este ejemplo te muestra como |
21 | colocar una figura en |
22 | cualquier lugar de la |
23 | ventana. |
24 | </p> |
25 | <output class="sprite" |
26 | style="left: 100px; |
27 | bottom: 150px"> |
28 | 😄 |
29 | </output> |
30 | </body> |
31 | |
32 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title> |
9 | Animación horizontal |
10 | </title> |
11 | <style> |
12 | .sprite { |
13 | position: fixed; |
14 | font-size: 3rem; |
15 | } |
16 | </style> |
17 | </head> |
18 | |
19 | <body> |
20 | <h1>Animación horizontal</h1> |
21 | <output id="carita" |
22 | class="sprite"> |
23 | 😄 |
24 | </output> |
25 | <script> |
26 | const REFRESCO = 5 |
27 | const VELOCIDAD = 0.5 |
28 | let x = 0 |
29 | setInterval(avanza, REFRESCO) |
30 | |
31 | function avanza() { |
32 | const y = innerHeight / 2 |
33 | const xMáxima = innerWidth |
34 | carita.style = |
35 | `left: ${x}px; bottom: ${y}px` |
36 | x = (x + VELOCIDAD) % xMáxima |
37 | } |
38 | </script> |
39 | </body> |
40 | |
41 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Animación recta</title> |
9 | <style> |
10 | .sprite { |
11 | position: fixed; |
12 | font-size: 3rem; |
13 | } |
14 | </style> |
15 | </head> |
16 | |
17 | <body> |
18 | <h1>Animación recta</h1> |
19 | <output id="carita" |
20 | class="sprite"> |
21 | 😄 |
22 | </output> |
23 | <script> |
24 | const X_INICIAL = 0 |
25 | const REFRESCO = 5 |
26 | const VELOCIDAD = 0.5 |
27 | let x = X_INICIAL |
28 | setInterval(avanza, REFRESCO) |
29 | |
30 | function avanza() { |
31 | const xFinal = innerWidth |
32 | const yInicial = innerHeight / 2 |
33 | const yFinal = innerHeight |
34 | const y = ((yFinal - yInicial) / |
35 | (xFinal - X_INICIAL)) * |
36 | (x - X_INICIAL) + |
37 | yInicial |
38 | carita.style = |
39 | `left: ${x}px; bottom: ${y}px` |
40 | x = (x + VELOCIDAD) % xFinal |
41 | } |
42 | </script> |
43 | </body> |
44 | |
45 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Ondula</title> |
9 | <style> |
10 | .sprite { |
11 | position: fixed; |
12 | font-size: 3rem; |
13 | } |
14 | </style> |
15 | </head> |
16 | |
17 | <body> |
18 | <h1>Ondula</h1> |
19 | <output id="carita" |
20 | class="sprite"> |
21 | 😄 |
22 | </output> |
23 | <script> |
24 | const REFRESCO = 5 |
25 | const VELOCIDAD = 0.5 |
26 | const FRECUENCIA = 0.03 |
27 | let x = 0 |
28 | setInterval(avanza, REFRESCO) |
29 | |
30 | function avanza() { |
31 | const xMáxima = innerWidth |
32 | const amplitud = innerHeight / 3 |
33 | const yBase = innerHeight / 2 |
34 | y = yBase + |
35 | amplitud * |
36 | Math.sin(FRECUENCIA * x) |
37 | carita.style = |
38 | `left: ${x}px; bottom: ${y}px` |
39 | x = (x + VELOCIDAD) % xMáxima |
40 | } |
41 | </script> |
42 | </body> |
43 | |
44 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Gira</title> |
9 | <style> |
10 | .sprite { |
11 | position: fixed; |
12 | font-size: 3rem; |
13 | } |
14 | </style> |
15 | </head> |
16 | |
17 | <body> |
18 | <h1>Gira</h1> |
19 | <output id="mariposa" |
20 | class="sprite"> |
21 | 🦋 |
22 | </output> |
23 | <script> |
24 | const REFRESCO = 120 |
25 | const VELOCIDAD = 0.3 |
26 | let angulo = 0 |
27 | setInterval(gira, REFRESCO) |
28 | |
29 | function gira() { |
30 | const xBase = innerWidth / 2 |
31 | const amplitudX = innerWidth / 3 |
32 | const yBase = innerHeight / 2 |
33 | const amplitudY = |
34 | innerHeight / 3 |
35 | const x = xBase + |
36 | amplitudX * Math.cos(angulo) |
37 | const y = yBase + |
38 | amplitudY * Math.sin(angulo) |
39 | mariposa.style = |
40 | `left: ${x}px; bottom: ${y}px` |
41 | angulo += VELOCIDAD |
42 | } |
43 | </script> |
44 | </body> |
45 | |
46 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Mueve con Botones</title> |
9 | <style> |
10 | .sprite { |
11 | position: fixed; |
12 | font-size: 3rem; |
13 | } |
14 | </style> |
15 | </head> |
16 | |
17 | <body> |
18 | <h1>Mueve con Botones</h1> |
19 | <p> |
20 | <button onclick="retrocede()"> |
21 | ◀ |
22 | </button> |
23 | <button onclick="avanza()"> |
24 | ▶ |
25 | </button> |
26 | </p> |
27 | <output id="carita" |
28 | class="sprite"> |
29 | 😄 |
30 | </output> |
31 | <script> |
32 | let yBase |
33 | let xMenor |
34 | let xMayor |
35 | const VELOCIDAD = 30 |
36 | actualiza() |
37 | let x = xMenor |
38 | dibuja() |
39 | |
40 | function retrocede() { |
41 | actualiza() |
42 | if (x > xMenor) { |
43 | x -= VELOCIDAD |
44 | } |
45 | dibuja() |
46 | } |
47 | |
48 | function avanza() { |
49 | actualiza() |
50 | if (x < xMayor) { |
51 | x += VELOCIDAD |
52 | } |
53 | dibuja() |
54 | } |
55 | |
56 | function actualiza() { |
57 | yBase = innerHeight / 2 |
58 | xMenor = innerWidth / 5 |
59 | xMayor = 4 * innerWidth / 5 |
60 | } |
61 | |
62 | function dibuja() { |
63 | carita.style = `left: ${x}px; |
64 | bottom: ${yBase}px` |
65 | } |
66 | </script> |
67 | </body> |
68 | |
69 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Choca</title> |
9 | <style> |
10 | .sprite { |
11 | position: fixed; |
12 | font-size: 3rem; |
13 | } |
14 | </style> |
15 | </head> |
16 | |
17 | <body> |
18 | <h1>Choca</h1> |
19 | <output id="abrazo" |
20 | class="sprite" |
21 | style="background-color: |
22 | greenyellow;"> |
23 | 🤗 |
24 | </output> |
25 | <output id="triste" |
26 | class="sprite" |
27 | style="background-color: |
28 | grey;"> |
29 | 😪 |
30 | </output> |
31 | <script> |
32 | let x = 0 |
33 | const REFRESCO = 5 |
34 | setInterval(avanza, REFRESCO) |
35 | |
36 | function avanza() { |
37 | const velocidad = |
38 | innerWidth / 2000 |
39 | const x2 = innerWidth |
40 | const y = innerHeight / 2 |
41 | triste.style.left = |
42 | `${innerWidth / 2}px` |
43 | triste.style.bottom = `${y}px` |
44 | abrazo.style.left = `${x}px` |
45 | abrazo.style.bottom = `${y}px` |
46 | if (!seTocan(abrazo, triste)) { |
47 | x = (x + velocidad) % x2 |
48 | } |
49 | } |
50 | |
51 | /** |
52 | * Devuelve true si 2 |
53 | * elementos se tocan. |
54 | * @param {HTMLElement} e1 |
55 | * @param {HTMLElement} e2 |
56 | * @returns {boolean} true |
57 | * si los elementos se |
58 | * tocan. |
59 | */ |
60 | function seTocan(e1, e2) { |
61 | const rE1 = |
62 | e1.getBoundingClientRect() |
63 | const rE2 = |
64 | e2.getBoundingClientRect() |
65 | return (rE1.right >= rE2.left |
66 | && rE1.left <= rE2.right |
67 | && rE1.top <= rE2.bottom |
68 | && rE1.bottom >= rE2.top) |
69 | } |
70 | </script> |
71 | </body> |
72 | |
73 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Sonrie</title> |
9 | <style> |
10 | .sprite { |
11 | position: fixed; |
12 | font-size: 3rem; |
13 | } |
14 | </style> |
15 | </head> |
16 | |
17 | <body> |
18 | <h1>Sonrie</h1> |
19 | <output id="abrazo" |
20 | class="sprite" |
21 | style="background-color: |
22 | greenyellow;"> |
23 | 🤗 |
24 | </output> |
25 | <output id="triste" |
26 | class="sprite" |
27 | style="background-color: |
28 | grey;"> |
29 | 😪 |
30 | </output> |
31 | <script> |
32 | let x = 0 |
33 | const REFRESCO = 5 |
34 | let intervalo = |
35 | setInterval(avanza, REFRESCO) |
36 | |
37 | function avanza() { |
38 | const velocidad = |
39 | innerWidth / 2000 |
40 | const x2 = innerWidth |
41 | const y = innerHeight / 2 |
42 | triste.style.left = |
43 | `${innerWidth / 2}px` |
44 | triste.style.bottom = `${y}px` |
45 | abrazo.style.left = `${x}px` |
46 | abrazo.style.bottom = `${y}px` |
47 | if (seTocan(abrazo, triste)) { |
48 | triste.value = "😊"; |
49 | triste.style. |
50 | backgroundColor = "pink"; |
51 | clearInterval(intervalo); |
52 | } else { |
53 | x = (x + velocidad) % x2 |
54 | } |
55 | } |
56 | |
57 | /** |
58 | * Devuelve true si 2 |
59 | * elementos se tocan. |
60 | * @param {HTMLElement} e1 |
61 | * @param {HTMLElement} e2 |
62 | * @returns {boolean} true |
63 | * si los elementos se |
64 | * tocan. |
65 | */ |
66 | function seTocan(e1, e2) { |
67 | const rE1 = |
68 | e1.getBoundingClientRect() |
69 | const rE2 = |
70 | e2.getBoundingClientRect() |
71 | return (rE1.right >= rE2.left |
72 | && rE1.left <= rE2.right |
73 | && rE1.top <= rE2.bottom |
74 | && rE1.bottom >= rE2.top) |
75 | } |
76 | </script> |
77 | </body> |
78 | |
79 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Mueve Aleatorio</title> |
9 | <style> |
10 | .sprite { |
11 | position: fixed; |
12 | font-size: 3rem; |
13 | } |
14 | </style> |
15 | </head> |
16 | |
17 | <body> |
18 | <h1>Mueve Aleatorio</h1> |
19 | <output id="carita" |
20 | class="sprite"> |
21 | 😄 |
22 | </output> |
23 | <script> |
24 | const REFRESCO = 5 |
25 | const RUIDO = 4 |
26 | let velocidad = 0.5 |
27 | let x = 0 |
28 | setInterval(avanza, REFRESCO) |
29 | |
30 | function avanza() { |
31 | const y = innerHeight / 2 |
32 | const xMáxima = innerWidth |
33 | carita.style.left = `${x}px` |
34 | carita.style.bottom = `${y}px` |
35 | x += velocidad + |
36 | aleatorio(-RUIDO, RUIDO) |
37 | if (x < 0) { |
38 | x = 0 |
39 | velocidad = -velocidad |
40 | } else if (x > xMáxima) { |
41 | x = xMáxima |
42 | velocidad = -velocidad |
43 | } |
44 | } |
45 | |
46 | /** |
47 | * Devuelve un número |
48 | * aleatorio entre el valor |
49 | * menor y el valor mayor. |
50 | * @param {number} menor el |
51 | * menor valor que se puede |
52 | * generar |
53 | * @param {number} mayor el |
54 | * mayor valor que se puede |
55 | * generar |
56 | * @returns {number} un |
57 | * número aleatorio entre |
58 | * menor y mayor. |
59 | */ |
60 | function |
61 | aleatorio(menor, mayor) { |
62 | /* Math.floor(x): elimina |
63 | * los decimales. |
64 | * Math.random(): genera |
65 | * un número aleatorio |
66 | * >= 0 y < 1. */ |
67 | return menor + |
68 | Math.floor( |
69 | Math.random() * |
70 | (mayor - menor + 1)) |
71 | } |
72 | </script> |
73 | </body> |
74 | |
75 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Custom Elements</title> |
9 | <style> |
10 | figura-web { |
11 | position: fixed; |
12 | font-size: 60px; |
13 | } |
14 | </style> |
15 | <script> |
16 | class FiguraWeb |
17 | extends HTMLElement { |
18 | connectedCallback() { |
19 | this.x = 0 |
20 | const attrY = |
21 | this.getAttribute("y") |
22 | const attrVel = |
23 | this.getAttribute("velocidad") |
24 | this.y = parseInt(attrY, 10) |
25 | this.velocidad = |
26 | parseInt(attrVel, 10) |
27 | } |
28 | muevete() { |
29 | this.style.right = |
30 | `${this.x}px` |
31 | this.style.top = `${this.y}px` |
32 | this.x = |
33 | (this.x + this.velocidad) % |
34 | innerWidth |
35 | } |
36 | } |
37 | customElements.define( |
38 | "figura-web", FiguraWeb) |
39 | </script> |
40 | </head> |
41 | |
42 | <body> |
43 | <h1>Custom Elements</h1> |
44 | <figura-web id="fantasma" |
45 | y="0" velocidad="20"> |
46 | 👻 |
47 | </figura-web> |
48 | <figura-web id="sonrisa" |
49 | y="100" velocidad="10"> |
50 | 😁 |
51 | </figura-web> |
52 | <script> |
53 | setInterval(anima, 120) |
54 | |
55 | function anima() { |
56 | fantasma.muevete() |
57 | sonrisa.muevete() |
58 | } |
59 | </script> |
60 | </body> |
61 | |
62 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Asociaciones</title> |
9 | <script> |
10 | /** |
11 | * Devuelve un número |
12 | * aleatorio entre el valor |
13 | * menor y el valor mayor. |
14 | * @param {number} menor el |
15 | * menor valor que se puede |
16 | * generar |
17 | * @param {number} mayor el |
18 | * mayor valor que se puede |
19 | * generar |
20 | * @returns {number} un |
21 | * número aleatorio entre |
22 | * menor y mayor. |
23 | */ |
24 | function |
25 | aleatorio(menor, mayor) { |
26 | /* Math.floor(x): elimina |
27 | * los decimales. |
28 | * Math.random(): genera |
29 | * un número aleatorio |
30 | * >= 0 y < 1. */ |
31 | return menor + |
32 | Math.floor( |
33 | Math.random() * |
34 | (mayor - menor + 1)) |
35 | } |
36 | |
37 | class PerroWeb |
38 | extends HTMLElement { |
39 | connectedCallback() { |
40 | this.x = 0 |
41 | this.y = 0 |
42 | this.innerHTML = "🐕" |
43 | this.style.position = "fixed" |
44 | this.style.fontSize = "2rem" |
45 | this.style.right = |
46 | `${this.x}px` |
47 | this.style.bottom = |
48 | `${this.y}px` |
49 | } |
50 | |
51 | muevete() { |
52 | this.x = (this.x + 30) % |
53 | innerWidth |
54 | this.style.right = |
55 | `${this.x}px` |
56 | } |
57 | } |
58 | customElements.define( |
59 | "perro-web", PerroWeb) |
60 | |
61 | class AguilaWeb |
62 | extends HTMLElement { |
63 | connectedCallback() { |
64 | this.x = aleatorio(0, |
65 | Math.floor(innerWidth)) |
66 | this.y = aleatorio(0, |
67 | Math.floor(innerHeight)) |
68 | this.innerHTML = "🦅" |
69 | this.style.position = "fixed" |
70 | this.style.fontSize = "2.5rem" |
71 | this.style.left = `${this.x}px` |
72 | this.style.top = `${this.y}px` |
73 | } |
74 | |
75 | muevete() { |
76 | this.y = (this.y + 10) % |
77 | innerHeight |
78 | this.style.top = `${this.y}px` |
79 | } |
80 | } |
81 | customElements.define( |
82 | "aguila-web", AguilaWeb) |
83 | |
84 | class ControladorWeb |
85 | extends HTMLElement { |
86 | connectedCallback() { |
87 | this.muevete = |
88 | this.muevete.bind(this) |
89 | this.innerHTML = /* html */ |
90 | `<button onclick="this. |
91 | parentElement.muevete()"> |
92 | Mueve |
93 | </button>` |
94 | this.perro = new PerroWeb() |
95 | this.aguilas = [ |
96 | new AguilaWeb(), |
97 | new AguilaWeb()] |
98 | this.append(this.perro) |
99 | for (const a of this.aguilas) { |
100 | this.append(a) |
101 | } |
102 | } |
103 | |
104 | muevete() { |
105 | this.perro.muevete() |
106 | for (let a of this.aguilas) { |
107 | a.muevete() |
108 | } |
109 | } |
110 | } |
111 | customElements.define( |
112 | "controlador-web", |
113 | ControladorWeb) |
114 | </script> |
115 | </head> |
116 | |
117 | <body> |
118 | <h1>Asociaciones</h1> |
119 | <controlador-web> |
120 | </controlador-web> |
121 | </body> |
122 | |
123 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Polimorfismo</title> |
9 | <script> |
10 | function |
11 | aleatorio(menor, mayor) { |
12 | return menor + |
13 | Math.floor( |
14 | Math.random() * |
15 | (mayor - menor + 1)) |
16 | } |
17 | |
18 | /** @interface */ |
19 | class SeMueve { |
20 | muevete() { |
21 | throw new Error("intf") |
22 | } |
23 | } |
24 | |
25 | /** @implements {SeMueve} */ |
26 | class PerroWeb |
27 | extends HTMLElement { |
28 | connectedCallback() { |
29 | this.x = 0 |
30 | this.y = 0 |
31 | this.innerHTML = "🐕" |
32 | this.style.position = "fixed" |
33 | this.style.fontSize = "2rem" |
34 | this.style.right = |
35 | `${this.x}px` |
36 | this.style.bottom = |
37 | `${this.y}px` |
38 | } |
39 | |
40 | muevete() { |
41 | this.x = (this.x + 30) % |
42 | window.innerWidth |
43 | this.style.right = |
44 | `${this.x}px` |
45 | } |
46 | } |
47 | customElements.define( |
48 | "perro-web", PerroWeb) |
49 | |
50 | /** @implements {SeMueve} */ |
51 | class AguilaWeb |
52 | extends HTMLElement { |
53 | connectedCallback() { |
54 | this.x = aleatorio(0, |
55 | Math.floor(innerWidth)) |
56 | this.y = aleatorio(0, |
57 | Math.floor(innerHeight)) |
58 | this.innerHTML = "🦅" |
59 | this.style.position = "fixed" |
60 | this.style.fontSize = "2.5rem" |
61 | this.style.left = `${this.x}px` |
62 | this.style.top = `${this.y}px` |
63 | } |
64 | |
65 | muevete() { |
66 | this.y = (this.y + 10) % |
67 | window.innerHeight |
68 | this.style.top = `${this.y}px` |
69 | } |
70 | } |
71 | customElements.define( |
72 | "aguila-web", AguilaWeb) |
73 | </script> |
74 | </head> |
75 | |
76 | <body> |
77 | <h1>Polimorfismo</h1> |
78 | <p> |
79 | <button onclick="mueve()"> |
80 | Mueve |
81 | </button> |
82 | </p> |
83 | <script> |
84 | const figuras = [ |
85 | new AguilaWeb(), |
86 | new PerroWeb(), |
87 | new AguilaWeb()] |
88 | for (let f of figuras) { |
89 | document.body.append(f) |
90 | } |
91 | function mueve() { |
92 | for (var f of figuras) { |
93 | f.muevete() |
94 | } |
95 | } |
96 | </script> |
97 | </body> |
98 | |
99 | </html> |
1 | <!DOCTYPE html> |
2 | <html> |
3 | |
4 | <head> |
5 | <meta charset="utf-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Jueguito 1</title> |
9 | <style> |
10 | body { |
11 | /* Rompe el flujo normal para |
12 | * poder hacer swipe hacia |
13 | * abajo. */ |
14 | position: fixed; |
15 | top: 0px; |
16 | left: 0px; |
17 | /* ocupa todo el espacio. */ |
18 | width: 100%; |
19 | height: 100%; |
20 | /* Elimina márgenes. */ |
21 | margin: 0; |
22 | /* Evita el scroll */ |
23 | overflow: hidden; |
24 | } |
25 | |
26 | .sprite { |
27 | position: fixed; |
28 | } |
29 | </style> |
30 | <script> |
31 | //@ts-check |
32 | class JugadorPaloma |
33 | extends HTMLElement { |
34 | connectedCallback() { |
35 | this.classList.add("sprite") |
36 | this.innerHTML += "🕊" |
37 | this.style.fontSize = "60px" |
38 | /* Coloca el elemento a la |
39 | * mitad de la pantalla. */ |
40 | const raiz = |
41 | document.documentElement |
42 | /* Obtiene las coordenadas del |
43 | * element. */ |
44 | const r = |
45 | this.getBoundingClientRect() |
46 | const left = |
47 | (raiz.clientWidth - r.width) / |
48 | 2 |
49 | const top = |
50 | (raiz.clientHeight - |
51 | r.height) / |
52 | 2 |
53 | this.style.left = `${left}px` |
54 | this.style.top = `${top}px` |
55 | } |
56 | |
57 | sube() { |
58 | const top = |
59 | this.getBoundingClientRect(). |
60 | top - |
61 | 20 |
62 | this.style.top = `${top}px` |
63 | } |
64 | |
65 | baja() { |
66 | const top = |
67 | this.getBoundingClientRect(). |
68 | top + |
69 | 20 |
70 | this.style.top = `${top}px` |
71 | } |
72 | |
73 | izquierda() { |
74 | const left = |
75 | this.getBoundingClientRect(). |
76 | left - |
77 | 20 |
78 | this.style.left = `${left}px` |
79 | } |
80 | |
81 | derecha() { |
82 | const left = |
83 | this.getBoundingClientRect(). |
84 | left + |
85 | 20 |
86 | this.style.left = `${left}px` |
87 | } |
88 | } |
89 | customElements.define( |
90 | "jugador-paloma", JugadorPaloma) |
91 | |
92 | class FiguraAguila |
93 | extends HTMLElement { |
94 | connectedCallback() { |
95 | this.classList.add("sprite") |
96 | this.innerHTML = "🦅" |
97 | this.style.fontSize = "40px" |
98 | const r = |
99 | this.getBoundingClientRect() |
100 | this.style.left = `${r.left}px` |
101 | this.style.top = `${r.top}px` |
102 | this.style.bottom = "auto" |
103 | this.style.right = "auto" |
104 | } |
105 | |
106 | /** |
107 | * Mueve la figura para que se |
108 | * acerque al jugador, usando la |
109 | * ecuación de la recta. |
110 | * @param {HTMLElement} jugador |
111 | * el jugador que es |
112 | * perseguido. |
113 | */ |
114 | muevete(jugador) { |
115 | const r = |
116 | this.getBoundingClientRect() |
117 | const rJ = jugador. |
118 | getBoundingClientRect() |
119 | const y2 = rJ.top |
120 | const y1 = r.top |
121 | const x2 = rJ.left |
122 | const x1 = r.left |
123 | const pendiente = x2 === x1 ? |
124 | 0 : |
125 | (y2 - y1) / (x2 - x1) |
126 | const dirección = |
127 | x2 > x1 ? 1 : -1 |
128 | const x = x1 + dirección * 5 |
129 | const y = |
130 | pendiente * (x - x1) + y1 |
131 | this.style.left = `${x}px` |
132 | this.style.top = `${y}px` |
133 | } |
134 | } |
135 | customElements.define( |
136 | "figura-aguila", FiguraAguila) |
137 | </script> |
138 | </head> |
139 | |
140 | <body> |
141 | <div> |
142 | <jugador-paloma></jugador-paloma> |
143 | <figura-aguila |
144 | style="right: 0; top: 0;"> |
145 | </figura-aguila> |
146 | <figura-aguila |
147 | style="right: 0; bottom: 0;"> |
148 | </figura-aguila> |
149 | </div> |
150 | <script> |
151 | //@ts-check |
152 | class Juego { |
153 | constructor() { |
154 | /** @type {JugadorPaloma} */ |
155 | this.jugador = document. |
156 | querySelector( |
157 | "jugador-paloma") |
158 | /** @type {FiguraAguila[]} */ |
159 | this.figuras = Array.from( |
160 | document.querySelectorAll( |
161 | "figura-aguila")) |
162 | this.iniciaX = null |
163 | this.iniciaY = null |
164 | this.interval = null |
165 | this.activo = true |
166 | } |
167 | |
168 | inicia() { |
169 | document.addEventListener( |
170 | "keydown", |
171 | evt => this.teclas(evt)) |
172 | this.interval = setInterval( |
173 | () => this.mueveFiguras(), 60) |
174 | } |
175 | |
176 | mueveFiguras() { |
177 | for (const f of this.figuras) { |
178 | f.muevete(this.jugador) |
179 | } |
180 | } |
181 | |
182 | /** @param {KeyboardEvent} ev*/ |
183 | teclas(ev) { |
184 | if (this.activo) { |
185 | switch (ev.key) { |
186 | case "ArrowLeft": |
187 | this.jugador.izquierda() |
188 | break |
189 | case "ArrowRight": |
190 | this.jugador.derecha() |
191 | break |
192 | case "ArrowUp": |
193 | this.jugador.sube() |
194 | break |
195 | case "ArrowDown": |
196 | this.jugador.baja() |
197 | break |
198 | } |
199 | } |
200 | } |
201 | } |
202 | |
203 | const juego = new Juego() |
204 | juego.inicia() |
205 | </script> |
206 | </body> |
207 | |
208 | </html> |
1 | <!DOCTYPE html> |
2 | <html> |
3 | |
4 | <head> |
5 | <meta charset="utf-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Jueguito 2</title> |
9 | <style> |
10 | body { |
11 | position: fixed; |
12 | top: 0px; |
13 | left: 0px; |
14 | width: 100%; |
15 | height: 100%; |
16 | margin: 0; |
17 | overflow: hidden; |
18 | } |
19 | |
20 | .sprite { |
21 | position: fixed; |
22 | } |
23 | </style> |
24 | <script> |
25 | //@ts-check |
26 | /** @abstract */ |
27 | class Jugador |
28 | extends HTMLElement { |
29 | izquierda() { |
30 | throw new Error("abstract") |
31 | } |
32 | derecha() { |
33 | throw new Error("abstract") |
34 | } |
35 | sube() { |
36 | throw new Error("abstract") |
37 | } |
38 | baja() { |
39 | throw new Error("abstract") |
40 | } |
41 | } |
42 | |
43 | /** @abstract */ |
44 | class Figura |
45 | extends HTMLElement { |
46 | /** |
47 | * @param {HTMLElement} jugador |
48 | * el jugador que persigue. |
49 | */ |
50 | muevete(jugador) { |
51 | throw new Error("abstract"); |
52 | } |
53 | } |
54 | |
55 | class Juego2 { |
56 | constructor() { |
57 | /** @type {Jugador} */ |
58 | this.jugador = document. |
59 | querySelector(".jugador") |
60 | /** @type {Figura[]} */ |
61 | this.figuras = Array.from( |
62 | document.querySelectorAll( |
63 | ".figura")) |
64 | this.iniciaX = null |
65 | this.iniciaY = null |
66 | this.interval = null |
67 | this.activo = true |
68 | } |
69 | |
70 | inicia() { |
71 | document.addEventListener( |
72 | "keydown", |
73 | evt => this.teclas(evt)) |
74 | document.addEventListener( |
75 | "touchstart", |
76 | evt => this.iniciaTouch(evt)) |
77 | document.addEventListener( |
78 | "touchmove", |
79 | evt => |
80 | this.desplazaTouch(evt)) |
81 | this.interval = setInterval( |
82 | () => this.mueveFiguras(), 60) |
83 | } |
84 | |
85 | mueveFiguras() { |
86 | for (const f of this.figuras) { |
87 | f.muevete(this.jugador) |
88 | } |
89 | this.detectaColisiones() |
90 | } |
91 | |
92 | detectaColisiones() { |
93 | for (const f of this.figuras) { |
94 | if (colisiona( |
95 | this.jugador, f)) { |
96 | this.termina() |
97 | break |
98 | } |
99 | } |
100 | } |
101 | |
102 | termina() { |
103 | this.activo = false |
104 | clearInterval(this.interval) |
105 | alert("Jueguito 2 terminado.") |
106 | } |
107 | |
108 | /** @param {KeyboardEvent} evt*/ |
109 | teclas(evt) { |
110 | if (this.activo) { |
111 | switch (evt.key) { |
112 | case "ArrowLeft": |
113 | this.jugador.izquierda() |
114 | break |
115 | case "ArrowRight": |
116 | this.jugador.derecha() |
117 | break |
118 | case "ArrowUp": |
119 | this.jugador.sube() |
120 | break |
121 | case "ArrowDown": |
122 | this.jugador.baja() |
123 | break |
124 | } |
125 | this.detectaColisiones() |
126 | } |
127 | } |
128 | |
129 | /** @param {TouchEvent} evt */ |
130 | iniciaTouch(evt) { |
131 | if (this.activo) { |
132 | const toqueInicial = |
133 | evt.touches[0] |
134 | this.iniciaX = |
135 | toqueInicial.clientX |
136 | this.iniciaY = |
137 | toqueInicial.clientY |
138 | } |
139 | } |
140 | |
141 | /** @param {TouchEvent} evt */ |
142 | desplazaTouch(evt) { |
143 | if (this.activo |
144 | && this.iniciaX |
145 | && this.iniciaY) { |
146 | const desplazamiento = |
147 | evt.touches[0] |
148 | var desplazamientoX = |
149 | desplazamiento.clientX |
150 | var desplazamientoY = |
151 | desplazamiento.clientY |
152 | var difX = desplazamientoX - |
153 | this.iniciaX |
154 | var difY = desplazamientoY - |
155 | this.iniciaY |
156 | /* Checa que el movimiento no |
157 | * sea muy corto. */ |
158 | if (Math.abs(difX) |
159 | + Math.abs(difY) |
160 | > 150) { |
161 | if (Math.abs(difX) |
162 | > Math.abs(difY)) { |
163 | if (difX > 70) { |
164 | this.jugador.derecha() |
165 | } else { |
166 | this.jugador.izquierda() |
167 | } |
168 | } else if (difY > 70) { |
169 | this.jugador.baja() |
170 | } else { |
171 | this.jugador.sube() |
172 | } |
173 | this.detectaColisiones() |
174 | // Reinicia valores. |
175 | this.iniciaX = null; |
176 | this.iniciaY = null; |
177 | } |
178 | } |
179 | } |
180 | } |
181 | |
182 | /** |
183 | * @param {HTMLElement} e1 |
184 | * @param {HTMLElement} e2 |
185 | * @returns {boolean} true si los |
186 | * element colisionan. |
187 | */ |
188 | function colisiona(e1, e2) { |
189 | const rE1 = |
190 | e1.getBoundingClientRect() |
191 | const rE2 = |
192 | e2.getBoundingClientRect() |
193 | return (rE1.right >= rE2.left |
194 | && rE1.left <= rE2.right |
195 | && rE1.top <= rE2.bottom |
196 | && rE1.bottom >= rE2.top) |
197 | } |
198 | |
199 | customElements.define( |
200 | "jugador-paloma", |
201 | class extends Jugador { |
202 | connectedCallback() { |
203 | this.classList.add("sprite") |
204 | this.classList.add("jugador") |
205 | this.innerHTML += "🕊" |
206 | this.style.fontSize = "60px" |
207 | const raiz = |
208 | document.documentElement |
209 | const r = |
210 | this.getBoundingClientRect() |
211 | const left = |
212 | (raiz.clientWidth |
213 | - r.width) / |
214 | 2 |
215 | const top = |
216 | (raiz.clientHeight - |
217 | r.height) / |
218 | 2 |
219 | this.style.left = `${left}px` |
220 | this.style.top = `${top}px` |
221 | } |
222 | |
223 | /** @override */ |
224 | sube() { |
225 | const top = |
226 | this.getBoundingClientRect(). |
227 | top - |
228 | 20 |
229 | this.style.top = `${top}px` |
230 | } |
231 | |
232 | /** @override */ |
233 | baja() { |
234 | const top = |
235 | this.getBoundingClientRect(). |
236 | top + |
237 | 20 |
238 | this.style.top = `${top}px` |
239 | } |
240 | |
241 | izquierda() { |
242 | const left = |
243 | this.getBoundingClientRect(). |
244 | left - |
245 | 20 |
246 | this.style.left = `${left}px` |
247 | } |
248 | |
249 | derecha() { |
250 | const left = |
251 | this.getBoundingClientRect(). |
252 | left + |
253 | 20 |
254 | this.style.left = `${left}px` |
255 | } |
256 | }) |
257 | |
258 | customElements.define( |
259 | "figura-aguila", |
260 | class extends Figura { |
261 | connectedCallback() { |
262 | this.classList.add("sprite") |
263 | this.classList.add("figura") |
264 | this.innerHTML = "🦅" |
265 | this.style.fontSize = "40px" |
266 | const r = |
267 | this.getBoundingClientRect() |
268 | this.style.left = |
269 | `${r.left}px` |
270 | this.style.top = `${r.top}px` |
271 | this.style.bottom = "auto" |
272 | this.style.right = "auto" |
273 | } |
274 | |
275 | /** |
276 | * @param {HTMLElement} jugador |
277 | * el jugador que es |
278 | * perseguido. |
279 | * @override |
280 | */ |
281 | muevete(jugador) { |
282 | const r = |
283 | this.getBoundingClientRect() |
284 | const rJ = jugador. |
285 | getBoundingClientRect() |
286 | const y2 = rJ.top |
287 | const y1 = r.top |
288 | const x2 = rJ.left |
289 | const x1 = r.left |
290 | const pendiente = x2 === x1 ? |
291 | 0 : |
292 | (y2 - y1) / (x2 - x1) |
293 | const dirección = |
294 | x2 > x1 ? 1 : -1 |
295 | const x = x1 + dirección * 5 |
296 | const y = |
297 | pendiente * (x - x1) + y1 |
298 | /* Evita que las figuras se |
299 | * peguen, añadiendo un |
300 | * movimiento aleatorio. */ |
301 | this.style.left = |
302 | `${desvía(x)}px` |
303 | this.style.top = |
304 | `${desvía(y)}px` |
305 | } |
306 | }) |
307 | |
308 | /** |
309 | * Obtiene una desviación |
310 | * aleatoria de 10 alrededor del |
311 | * valor i. |
312 | * @param {number} i valor base |
313 | */ |
314 | function desvía(i) { |
315 | return i + 10 - |
316 | 20 * Math.random() |
317 | } |
318 | </script> |
319 | </head> |
320 | |
321 | <body> |
322 | <jugador-paloma></jugador-paloma> |
323 | <figura-aguila |
324 | style="right: 0; top: 0;"> |
325 | </figura-aguila> |
326 | <figura-aguila |
327 | style="right: 0; bottom: 0;"> |
328 | </figura-aguila> |
329 | <script> |
330 | //@ts-check |
331 | const juego2 = new Juego2() |
332 | juego2.inicia() |
333 | </script> |
334 | </body> |
335 | |
336 | </html> |
1 | <!DOCTYPE html> |
2 | <html> |
3 | |
4 | <head> |
5 | <meta charset="utf-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Jueguito 3</title> |
9 | <style> |
10 | body { |
11 | position: fixed; |
12 | top: 0px; |
13 | left: 0px; |
14 | width: 100%; |
15 | height: 100%; |
16 | margin: 0; |
17 | overflow: hidden; |
18 | } |
19 | |
20 | .sprite { |
21 | position: fixed; |
22 | } |
23 | </style> |
24 | <script> |
25 | //@ts-check |
26 | /** @abstract */ |
27 | class Jugador |
28 | extends HTMLElement { |
29 | /** @param {number} velocidad */ |
30 | izquierda(velocidad) { |
31 | throw new Error("abstract") |
32 | } |
33 | /** @param {number} velocidad */ |
34 | derecha(velocidad) { |
35 | throw new Error("abstract") |
36 | } |
37 | /** @param {number} velocidad */ |
38 | sube(velocidad) { |
39 | throw new Error("abstract") |
40 | } |
41 | /** @param {number} velocidad */ |
42 | baja(velocidad) { |
43 | throw new Error("abstract") |
44 | } |
45 | } |
46 | |
47 | /** @abstract */ |
48 | class Figura |
49 | extends HTMLElement { |
50 | /** |
51 | * @param {HTMLElement} jugador |
52 | * el jugador que es |
53 | * perseguido. |
54 | */ |
55 | muevete(jugador) { |
56 | throw new Error("abstract") |
57 | } |
58 | } |
59 | |
60 | /** @interface */ |
61 | class Fabrica { |
62 | /** |
63 | * Devuelve el único jugador, |
64 | * por lo que se considera |
65 | * Singleton. |
66 | * @returns {Jugador} |
67 | */ |
68 | jugador() { |
69 | throw new Error("interface") |
70 | } |
71 | /** |
72 | * Devuelve un arreglo con las |
73 | * figuras del juego. |
74 | * @returns {Figura[]} |
75 | */ |
76 | figuras() { |
77 | throw new Error("interface") |
78 | } |
79 | } |
80 | |
81 | class Juego3 { |
82 | /** @param {Fabrica} fabrica */ |
83 | constructor(fabrica) { |
84 | this.jugador = |
85 | fabrica.jugador() |
86 | this.figuras = |
87 | fabrica.figuras() |
88 | this.iniciaX = null |
89 | this.iniciaY = null |
90 | this.interval = null |
91 | this.activo = true |
92 | } |
93 | |
94 | inicia() { |
95 | document.addEventListener( |
96 | "keydown", |
97 | evt => this.teclas(evt)) |
98 | document.addEventListener( |
99 | "touchstart", |
100 | evt => this.iniciaTouch(evt)) |
101 | document.addEventListener( |
102 | "touchmove", |
103 | evt => |
104 | this.desplazaTouch(evt)) |
105 | this.interval = setInterval( |
106 | () => this.mueveFiguras(), 60) |
107 | } |
108 | |
109 | mueveFiguras() { |
110 | for (const f of this.figuras) { |
111 | f.muevete(this.jugador) |
112 | } |
113 | this.detectaColisiones() |
114 | } |
115 | |
116 | detectaColisiones() { |
117 | for (const f of this.figuras) { |
118 | if (colisiona( |
119 | this.jugador, f)) { |
120 | this.termina() |
121 | break |
122 | } |
123 | } |
124 | } |
125 | |
126 | termina() { |
127 | this.activo = false |
128 | clearInterval(this.interval) |
129 | this.jugador.innerHTML = "💥" |
130 | } |
131 | |
132 | /** @param {KeyboardEvent} evt*/ |
133 | teclas(evt) { |
134 | if (this.activo) { |
135 | switch (evt.key) { |
136 | case "ArrowLeft": |
137 | this.jugador.izquierda(20) |
138 | break |
139 | case "ArrowRight": |
140 | this.jugador.derecha(20) |
141 | break |
142 | case "ArrowUp": |
143 | this.jugador.sube(20) |
144 | break |
145 | case "ArrowDown": |
146 | this.jugador.baja(20) |
147 | break |
148 | } |
149 | this.detectaColisiones() |
150 | } |
151 | } |
152 | |
153 | /** @param {TouchEvent} evt */ |
154 | iniciaTouch(evt) { |
155 | if (this.activo) { |
156 | const toqueInicial = |
157 | evt.touches[0] |
158 | this.iniciaX = |
159 | toqueInicial.clientX |
160 | this.iniciaY = |
161 | toqueInicial.clientY |
162 | } |
163 | } |
164 | |
165 | /** @param {TouchEvent} evt */ |
166 | desplazaTouch(evt) { |
167 | if (this.activo |
168 | && this.iniciaX |
169 | && this.iniciaY) { |
170 | const desplazamiento = |
171 | evt.touches[0] |
172 | var desplazamientoX = |
173 | desplazamiento.clientX |
174 | var desplazamientoY = |
175 | desplazamiento.clientY |
176 | var difX = desplazamientoX - |
177 | this.iniciaX |
178 | var difY = desplazamientoY - |
179 | this.iniciaY |
180 | if (Math.abs(difX) |
181 | + Math.abs(difY) |
182 | > 150) { |
183 | if (Math.abs(difX) |
184 | > Math.abs(difY)) { |
185 | if (difX > 70) { |
186 | this.jugador.derecha(40) |
187 | } else { |
188 | this.jugador.izquierda(40) |
189 | } |
190 | } else if (difY > 70) { |
191 | this.jugador.baja(40) |
192 | } else { |
193 | this.jugador.sube(40) |
194 | } |
195 | this.detectaColisiones() |
196 | this.iniciaX = null |
197 | this.iniciaY = null |
198 | } |
199 | } |
200 | } |
201 | } |
202 | |
203 | /** |
204 | * @param {HTMLElement} e1 |
205 | * @param {HTMLElement} e2 |
206 | * @returns {boolean} true si los |
207 | * element colisionan. |
208 | */ |
209 | function colisiona(e1, e2) { |
210 | const rE1 = |
211 | e1.getBoundingClientRect() |
212 | const rE2 = |
213 | e2.getBoundingClientRect() |
214 | return (rE1.right >= rE2.left |
215 | && rE1.left <= rE2.right |
216 | && rE1.top <= rE2.bottom |
217 | && rE1.bottom >= rE2.top) |
218 | } |
219 | |
220 | customElements.define( |
221 | "jugador-paloma", |
222 | class extends Jugador { |
223 | connectedCallback() { |
224 | this.classList.add("sprite") |
225 | this.innerHTML += "🕊" |
226 | this.style.fontSize = "60px" |
227 | const raiz = |
228 | document.documentElement |
229 | const r = |
230 | this.getBoundingClientRect() |
231 | const left = |
232 | (raiz.clientWidth |
233 | - r.width) / |
234 | 2 |
235 | const top = |
236 | (raiz.clientHeight - |
237 | r.height) / |
238 | 2 |
239 | this.style.left = `${left}px` |
240 | this.style.top = `${top}px` |
241 | } |
242 | |
243 | /** |
244 | * @param {number} velocidad |
245 | * @override |
246 | */ |
247 | sube(velocidad) { |
248 | const top = |
249 | this.getBoundingClientRect(). |
250 | top - |
251 | velocidad |
252 | this.style.top = `${top}px` |
253 | } |
254 | |
255 | /** |
256 | * @param {number} velocidad |
257 | * @override |
258 | */ |
259 | baja(velocidad) { |
260 | const top = |
261 | this.getBoundingClientRect(). |
262 | top + |
263 | velocidad |
264 | this.style.top = `${top}px` |
265 | } |
266 | |
267 | /** |
268 | * @param {number} velocidad |
269 | * @override |
270 | */ |
271 | izquierda(velocidad) { |
272 | const left = |
273 | this.getBoundingClientRect(). |
274 | left - |
275 | velocidad |
276 | this.style.left = `${left}px` |
277 | } |
278 | |
279 | /** |
280 | * @param {number} velocidad |
281 | * @override |
282 | */ |
283 | derecha(velocidad) { |
284 | const left = |
285 | this.getBoundingClientRect(). |
286 | left + |
287 | velocidad |
288 | this.style.left = `${left}px` |
289 | } |
290 | }) |
291 | |
292 | customElements.define( |
293 | "figura-aguila", |
294 | class extends Figura { |
295 | connectedCallback() { |
296 | this.classList.add("sprite") |
297 | this.innerHTML = "🦅" |
298 | this.style.fontSize = "40px" |
299 | const r = |
300 | this.getBoundingClientRect() |
301 | this.style.left = |
302 | `${r.left}px` |
303 | this.style.top = `${r.top}px` |
304 | this.style.bottom = "auto" |
305 | this.style.right = "auto" |
306 | } |
307 | |
308 | /** |
309 | * @param {HTMLElement} jugador |
310 | * el jugador que persigue. |
311 | * @override |
312 | */ |
313 | muevete(jugador) { |
314 | const r = |
315 | this.getBoundingClientRect() |
316 | const rJ = jugador. |
317 | getBoundingClientRect() |
318 | const y2 = rJ.top |
319 | const y1 = r.top |
320 | const x2 = rJ.left |
321 | const x1 = r.left |
322 | const pendiente = x2 === x1 ? |
323 | 0 : |
324 | (y2 - y1) / (x2 - x1) |
325 | const dirección = |
326 | x2 > x1 ? 1 : -1 |
327 | const x = x1 + dirección * 5 |
328 | const y = |
329 | pendiente * (x - x1) + y1 |
330 | this.style.left = |
331 | `${desvía(x)}px` |
332 | this.style.top = |
333 | `${desvía(y)}px` |
334 | } |
335 | }) |
336 | |
337 | function desvía(i) { |
338 | return i + 10 - |
339 | 20 * Math.random() |
340 | } |
341 | </script> |
342 | </head> |
343 | |
344 | <body> |
345 | <jugador-paloma></jugador-paloma> |
346 | <figura-aguila |
347 | style="right: 0; top: 0;"> |
348 | </figura-aguila> |
349 | <figura-aguila |
350 | style="right: 0; bottom: 0;"> |
351 | </figura-aguila> |
352 | <script> |
353 | //@ts-check |
354 | /** @implements {Fabrica} */ |
355 | class MiFabrica { |
356 | constructor() { |
357 | /** @type {Jugador} */ |
358 | this.jugadorSingleton = |
359 | document.querySelector( |
360 | "jugador-paloma"); |
361 | } |
362 | /** |
363 | * Devuelve el único jugador, |
364 | * por lo que se considera |
365 | * Singleton. |
366 | * @returns {Jugador} |
367 | */ |
368 | jugador() { |
369 | return this.jugadorSingleton |
370 | } |
371 | /** |
372 | * Devuelve un arreglo con las |
373 | * figuras del juego. |
374 | * @returns {Figura[]} |
375 | */ |
376 | figuras() { |
377 | return Array.from( |
378 | document.querySelectorAll( |
379 | "figura-aguila")) |
380 | } |
381 | } |
382 | const juego = |
383 | new Juego3(new MiFabrica()) |
384 | juego.inicia() |
385 | </script> |
386 | </body> |
387 | |
388 | </html> |
En esta lección se revisaron los elementos principales para elaborar formularios y se presentaron algunos ejemplos.
En esta lección se presentan ejemplos de adornos en una página web.
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Adorno Horizontal</title> |
9 | <style> |
10 | .sprite { |
11 | position: fixed; |
12 | } |
13 | </style> |
14 | </head> |
15 | |
16 | <body> |
17 | <h1>Adorno Horizontal</h1> |
18 | <script> |
19 | const Y = 0 |
20 | const DISTANCIA = 20 |
21 | const X_MÁXIMA = innerWidth |
22 | let x = 0 |
23 | /** |
24 | * En esta variable se agrega el |
25 | * HTML de las figuras que forman |
26 | * el adorno. |
27 | */ |
28 | let inner = "" |
29 | while (x < X_MÁXIMA) { |
30 | /* Agrega el HTML de un emoji a |
31 | * inner. */ |
32 | inner += /* html */ |
33 | `<div class="sprite" |
34 | style="top: ${Y}px; |
35 | left: ${x}px;"> |
36 | 💕 |
37 | </div>` |
38 | x += DISTANCIA |
39 | } |
40 | /* Agrega las figuras al HTML de |
41 | * body. */ |
42 | document.body.innerHTML += inner |
43 | </script> |
44 | </body> |
45 | |
46 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="utf-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Línea</title> |
9 | </head> |
10 | |
11 | <body> |
12 | <script> |
13 | for (let x = 0; x < 200 |
14 | ; x += 20) { |
15 | let y = 0.45 * x + 30; |
16 | document.body.innerHTML += |
17 | /* html */ |
18 | `<div |
19 | style="position: absolute; |
20 | bottom: ${y}px; |
21 | left: ${x}px;"> |
22 | 💕 |
23 | </div>` |
24 | } |
25 | </script> |
26 | </body> |
27 | |
28 | </html> |
1 | <!DOCTYPE html> |
2 | <html lang="es"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" |
7 | content="width=device-width"> |
8 | <title>Adorno con Giro</title> |
9 | <style> |
10 | .sprite { |
11 | position: fixed; |
12 | } |
13 | </style> |
14 | </head> |
15 | |
16 | <body> |
17 | <h1>Adorno con Giro</h1> |
18 | <script> |
19 | const INCREMENTO = |
20 | 2 * Math.PI / 21 |
21 | const X_BASE = innerWidth / 2 |
22 | const Y_BASE = innerHeight / 2 |
23 | const ANGULO_FINAL = 6 * Math.PI |
24 | const amplitud = Math.min( |
25 | window.innerHeight, |
26 | window.innerWidth) / |
27 | (3 * ANGULO_FINAL) |
28 | let inner = "" |
29 | for (let angulo = 0 |
30 | ; angulo < ANGULO_FINAL |
31 | ; angulo += INCREMENTO) { |
32 | const r = amplitud * angulo |
33 | const x = |
34 | X_BASE + r * Math.cos(angulo) |
35 | const y = |
36 | Y_BASE + r * Math.sin(angulo) |
37 | inner += /* html */ |
38 | `<div class="sprite" |
39 | style="bottom: ${y}px; |
40 | left: ${x}px;"> |
41 | ⌛ |
42 | </div>` |
43 | } |
44 | document.body.innerHTML += inner |
45 | </script> |
46 | </body> |
47 | |
48 | </html> |
En esta lección se revisó como poner adornos a una página web.