Maquetación CSS
Buenas prácticas
Buenas prácticas: Pasos previos
Buenas prácticas: Resets CSS
Orden de la cascada
Buenas prácticas: Resets CSS
Buenas prácticas: Resets CSS
Buenas prácticas: Resets CSS
See the Pen CAP - Html limpio by Iván Albizu (@ivan_albizu) on CodePen.
Buenas prácticas: Defensive CSS
Preprocesador SASS
Preprocesador SASS: Transpilación
Preprocesador SASS: Indentación
.nav .list {
margin: 0;
padding: 0;
}
.nav .list .list-item {
display: inline-block;
}
Preprocesador SASS: Indentación
.nav .list {
margin: 0;
padding: 0;
}
.nav .list .list-item {
display: inline-block;
}
Preprocesador SASS: Indentación
.nav {
.list {
margin: 0;
padding: 0;
}
}
.nav .list .list-item {
display: inline-block;
}
Preprocesador SASS: Indentación
.nav {
.list {
margin: 0;
padding: 0;
}
}
.nav .list .list-item {
display: inline-block;
}
Preprocesador SASS: Indentación
.nav {
.list {
margin: 0;
padding: 0;
}
.list .list-item {
display: inline-block;
}
}
Preprocesador SASS: Indentación
.nav {
.list {
margin: 0;
padding: 0;
.list-item {
display: inline-block;
}
}
}
Preprocesador SASS: Variables
$color-primary: #cc0; //definición de variable SASS
.nav {
color: $color-primary; //uso de variable SASS
}
.logo {
outline: 1px solid $color-primary; //uso de variable SASS
}
Preprocesador SASS: Variables
$color-primary: #cc0; //definición de variable SASS
.nav {
color: $color-primary; //uso de variable SASS
}
.logo {
outline: 1px solid $color-primary; //uso de variable SASS
}
Preprocesador SASS: Variables
$color-primary: #cc0; //definición de variable SASS
.nav {
color: #cc0; //lo que le llega al navegador
}
.logo {
outline: 1px solid #cc0; //lo que le llega al navegador
}
Preprocesador SASS: Variables
See the Pen CAP - Sass variables by Iván Albizu (@ivan_albizu) on CodePen.
Preprocesador SASS: Operador "&"
.header {
// some code
&__nav {
// perhaps, more code
}
}
Preprocesador SASS: Operador "&"
.header {
// some code
}
.header__nav {
// perhaps, more code
}
Preprocesador SASS: Operador "&"
.link {
// some code
&.is-active {
// perhaps, more code
}
}
Preprocesador SASS: Operador "&"
.link {
// some code
}
.link.is-active {
// perhaps, more code
}
Preprocesador SASS: Mixins
@mixin theme($theme: DarkGray) {
background: $theme;
box-shadow: 0 0 1px rgba($theme, .25);
color: #fff;
}
Preprocesador SASS: Mixins
@mixin theme($theme: DarkGray) {
background: $theme;
box-shadow: 0 0 1px rgba($theme, .25);
color: #fff;
}
.info {
@include theme;
}
.alert {
@include theme($theme: DarkRed);
}
Preprocesador SASS: Mixins
@mixin theme($theme: DarkGray) {
background: $theme;
box-shadow: 0 0 1px rgba($theme, .25);
color: #fff;
}
.info {
background: DarkGray;
box-shadow: 0 0 1px rgba(169, 169, 169, 0.25);
color: #fff;
}
.alert {
background: DarkRed;
box-shadow: 0 0 1px rgba(139, 0, 0, 0.25);
color: #fff;
}
Preprocesador SASS: Maps
$theme-colors: (
"primary": $primary,
"danger": $danger
);
body {
background-color: map-get($theme-colors, "primary");
}
// el uso de map-get suele ser mediante función auxiliar para
// evitar posibles errores al no encontrar la 'key' o 'values' inesperados
// ejemplo: https://gist.github.com/lewismcarey/de2a70fe93ab235ba103
Preprocesador SASS: Funciones / Loops
Ejemplo de uso, no entramos en detalles
See the Pen fluid css by Iván Albizu (@ivan_albizu) on CodePen.
Metodología BEM
Metodología BEM: sintáxis
Metodología BEM: ejemplo header
See the Pen CAP - BEM menu by Iván Albizu (@ivan_albizu) on CodePen.
Custom Property
Custom Property: definición
--main-color: #32022c; // definición de Property y asignación de valor
color: var(--main-color);
border-color: var(--main-color, purple);
Custom Property: definición
--main-color: #32022c; // definición de Property y asignación de valor
color: var(--main-color); // uso de Property
border-color: var(--main-color, purple);
Custom Property: definición
--main-color: #32022c; // definición de Property y asignación de valor
color: var(--main-color); // uso de Property
border-color: var(--main-color, purple); // uso de Property con fallback
Custom Property: ámbito
// en cualquier regla CSS tendrá este valor
// salvo que se sobreescriba en otra regla
:root {
--main-color: #32022c;
}
// nuevo valor para la Property
// para cualquier elemento que esté dentro de ".nav"
// salvo que se sobreescriba en otra regla hija
.nav {
--main-color: #022;
}
Custom Property: ámbito
// en cualquier regla CSS tendrá este valor
// salvo que se sobreescriba en otra regla
:root {
--main-color: #32022c;
}
// nuevo valor para la Property
// para cualquier elemento que esté dentro de ".nav"
// salvo que se sobreescriba en otra regla hija
.nav {
--main-color: #022;
}
Custom Property: ámbito
// en cualquier regla CSS tendrá este valor
// salvo que se sobreescriba en otra regla
:root {
--main-color: #32022c;
}
// nuevo valor para la Property
// para cualquier elemento que esté dentro de ".nav"
// salvo que se sobreescriba en otra regla hija
.nav {
--main-color: #022;
.item {
--main-color: #bbb022;
}
}
Custom Property: registro
@property --coordinate-x {
initial-value: 50%;
inherits: true;
syntax: '<percentage>';
}
Custom Property: registro
See the Pen Transition for custom Property (css Vars) by Iván Albizu (@ivan_albizu) on CodePen.
Custom Property: ejemplo mejora accesibilidad
:root {
--t-delay-btn: .3s;
--t-duration-btn: .5s;
}
Custom Property: ejemplo mejora accesibilidad
:root {
--t-delay-btn: .3s;
--t-duration-btn: .5s;
}
.btn {
transition: all var(--t-duration-btn) linear var(--t-delay-btn);
&:hover,
&:focus {
transition: all var(--t-duration-btn) linear var(--t-delay-btn);
}
}
Custom Property: ejemplo mejora accesibilidad
:root {
--t-delay-btn: .3s;
--t-duration-btn: .5s;
}
@media screen and (prefers-reduced-motion: reduce) {
:root {
--t-delay-btn: 0.01ms;
--t-duration-btn: 0.01ms;
}
}
.btn {
transition: all var(--t-duration-btn) linear var(--t-delay-btn);
&:hover,
&:focus {
transition: all var(--t-duration-btn) linear var(--t-delay-btn);
}
}
Custom Property: ejemplo mejora accesibilidad
See the Pen Prefers Reduced Motion by Iván Albizu (@ivan_albizu) on CodePen.
Custom Property: ejemplo Web component
:host button:hover,
:host button:focus-within {
outline: 2px solid var(--color-tab-active-background, #5A3A31);
}
:host .js-active-tab-bg {
background-color: var(--color-tab-active-background, #5A3A31);
}
Custom Property: ejemplo Web component
See the Pen WebComponent Tabs with Slots by Iván Albizu (@ivan_albizu) on CodePen.
Taller CSS
https://github.com/ivanalbizu/taller-cssRamas:
Nuevas (y no tan nuevas) features CSS
@container CSS
¿Qué es @container?
spoiler
Estado actual @container size - Caniuse
Estado actual @container units - Caniuse
Estado actual @container style
Estado actual - @supports
@supports not (container: inline-size) {
.warning {
display: block;
}
}
@supports (selector(:has(*))) {
body {
background-color: red
}
}
Definición de @container | HTML
Definición de @container | CSS
[data-container="btn"] {
container-type: inline-size;// size | inline-size | normal
container-name: btns;
//container: <container-name> / <container-type>;
}
.btn-groups {
display: flex;
flex-direction: column;
}
@container btns (min-width: 300px) {
.btn-groups {
flex-direction: row;
}
}
@container (width > 900px) {
.card {
--bg-color: brown;
--padding: 16px;
}
}
Unidades propias de @container
Unidades propias de @container
.title-card {
font-size: clamp(1rem, 3cqi + 1rem, 4rem);
line-height: 1.1;
margin-bottom: 1rem;
}
@container style()
@container style(--type: primary) {
.card {
border: 0.5rem dotted currentColor;
}
@container style(--sub-type: narrow) {
.card {
border-width: 0.2rem;
}
}
@container style(--sub-type: wide) {
.card {
border-width: 1rem;
}
}
}
@container style(--type: primary) or style(--type: secondary) {
// some styles
}
@container size + style()
@container card (min-width: 600px) and style(--responsive: true) {
.card {
outline: 2px solid currentColor;
outline-offset: -8px;
}
}
Ejemplo I: @container querie
See the Pen CSS @container by Iván Albizu (@ivan_albizu) on CodePen.
Ejemplo II: @container querie + unit
See the Pen Container Queries + Container Units by Iván Albizu (@ivan_albizu) on CodePen.
Ejemplo III: @container style()
See the Pen Untitled by Iván Albizu (@ivan_albizu) on CodePen.
Ejemplo IV: @container style()
See the Pen CSS @containers | nested + layers by Iván Albizu (@ivan_albizu) on CodePen.
Recursos de interés
Ahmad Shadeed - container queriesEnd
Un gran poder conlleva una gran responsabilidad
CSS houdini
Ampliar información de manera más técnica y con más ejemplos
Charla en youtube by Joan León
CSSOM
APIs definidas aunque no todas disponibles
CSS Painting API
CSS Painting API: registro
class BtnPulse {
paint(ctx, size, props) {
// Code
}
}
registerPaint('btn-pulse', BtnPulse);
CSS Painting API: registro (codepen)
// Opción para usarlo en Codepen
(async () => {
if (typeof CSS === 'undefined' || !('paintWorklet' in CSS)) {
await import("https://unpkg.com/css-paint-polyfill");
}
const paintModule = URL.createObjectURL(new Blob(
[ document.querySelector('[type="houdini/paint-worklet"]').textContent ],
{ type: "text/javascript" }
));
await CSS.paintWorklet.addModule(paintModule);
})()
CSS Painting API: uso
@supports (background: paint(something)) {
.element {
background: tomato paint(btn-pulse);
border-image: paint(another-houdini-definition);
}
}
CSS Painting API: Canvas I
registerPaint('btn-pulse', class {
static get contextOptions() { }
static get inputArguments() { }
static get inputProperties() { }
_paintCircles(ctx, fillStyle, strokeStyle, x, y, rad) { }
paint(ctx, size, props) { }
})
CSS Painting API: Canvas II
registerPaint('btn-pulse', class {
static get contextOptions() { }
static get inputArguments() { }
static get inputProperties() {
return []
}
_paintCircles(ctx, fillStyle, strokeStyle, x, y, rad) { }
paint(ctx, size, props) { }
})
CSS Painting API: Canvas III
registerPaint('btn-pulse', class {
static get contextOptions() { }
static get inputArguments() { }
static get inputProperties() {
return [
'--x',
'--y',
'--rad',
'--pulse-rad',
'--fill',
'--pulse-stroke-color'
]
}
_paintCircles(ctx, fillStyle, strokeStyle, x, y, rad) { }
paint(ctx, size, props) { }
})
CSS Painting API: Canvas IV
registerPaint('btn-pulse', class {
static get contextOptions() { }
static get inputArguments() { }
static get inputProperties() {
return [
'--x',
'--y',
'--rad',
'--pulse-rad',
'--fill',
'--pulse-stroke-color'
]
}
_paintCircles(ctx, fillStyle, strokeStyle, x, y, rad) {}
paint(ctx, size, props) { }
})
CSS Painting API - Canvas V
registerPaint('btn-pulse', class {
static get contextOptions() { }
static get inputArguments() { }
static get inputProperties() {
return [
'--x',
'--y',
'--rad',
'--pulse-rad',
'--fill',
'--pulse-stroke-color'
]
}
_paintCircles(ctx, fillStyle, strokeStyle, x, y, rad) {
ctx.beginPath()
ctx.fillStyle = fillStyle
ctx.strokeStyle = strokeStyle
ctx.arc(x, y, rad, 0, 2 * Math.PI)
ctx.fill()
ctx.stroke()
}
paint(ctx, size, props) { }
})
CSS Painting API: Canvas VI
registerPaint('btn-pulse', class {
static get contextOptions() { }
static get inputArguments() { }
static get inputProperties() {
return [
'--x',
'--y',
'--rad',
'--pulse-rad',
'--fill',
'--pulse-stroke-color'
]
}
_paintCircles(ctx, fillStyle, strokeStyle, x, y, rad) {
ctx.beginPath()
ctx.fillStyle = fillStyle
ctx.strokeStyle = strokeStyle
ctx.arc(x, y, rad, 0, 2 * Math.PI)
ctx.fill()
ctx.stroke()
}
paint(ctx, size, props) { }
})
CSS Painting API: Canvas VII
registerPaint('btn-pulse', class {
static get contextOptions() { }
static get inputArguments() { }
static get inputProperties() {
return [
'--x',
'--y',
'--rad',
'--pulse-rad',
'--fill',
'--pulse-stroke-color'
]
}
_paintCircles(ctx, fillStyle, strokeStyle, x, y, rad) {
ctx.beginPath()
ctx.fillStyle = fillStyle
ctx.strokeStyle = strokeStyle
ctx.arc(x, y, rad, 0, 2 * Math.PI)
ctx.fill()
ctx.stroke()
}
paint(ctx, size, props) {
const x = props.get('--x')
const y = props.get('--y')
const rad = props.get('--rad')
const fill = (props.get('--fill')).toString()
const pulseRad = props.get('--pulse-rad')
const pulseStrokeColor = (props.get('--pulse-stroke-color')).toString()
this._paintCircles(ctx, fill, '#fff', x.value, y.value, rad.value)
this._paintCircles(ctx, 'transparent', pulseStrokeColor, x.value, y.value, pulseRad.value + rad.value)
}
})
See the Pen CSS Houdini Paint API - bezierCurve by Iván Albizu (@ivan_albizu) on CodePen.
@layer
@layer definición
@charset "UTF-8"
@layer theme {rules};
@layer theme;
@layer theme, layout, utilities;
@layer {rules}
Estado actual @layer: Caniuse
Capas @layer
!important@layer: Orden de la cascada
@layer importación
@charset "UTF-8";
@layer reset;
@import url("bootstrap.css");
@import url("bootstrap.css") layer(framework);
@layer nested
@layer outer {
@layer inner {
.button {
color: red;
}
}
}
@layer outer.inner {
.another {
color: green;
}
}
@layer non-layered
@layer base {
#button.super-specific {
color: red;
}
}
button {
color: green;
}
Ejemplos
SimpleRecursos interesantes
CSS tricks
Funciones CSS + pseudo clases
Funciones CSS + pseudo clases
| Display state | :fullscreen | :modal | :picture-in-picture |
| Linguistic | :dir() | :lang() |
| Input pseudo-classes | :autofill | :enabled | :disabled | :read-only | :read-write | :placeholder-shown | :default | :checked | :indeterminate | :blank | :valid | :invalid | :in-range | :out-of-range | :required | :optional | :user-invalid |
| Location | :any-link | :link | :visited | :local-link | :target | :target-within | :scope |
| DOM structure | :root | :empty | :nth-child | :nth-last-child | :first-child | :last-child | :only-child | :nth-of-type | :nth-last-of-type | :first-of-type | :last-of-type | :only-of-type |
| User action | :hover | :active | :focus | :focus-visible | :focus-within |
| Functional | :is() | :not() | :where() | :has() |
Contrast Theme
Display Modes
Contrast Theme I
Windows 10: High Contrast
Windows 11: Contrast Themes
MacOS: Accessibility > Displays > Increase contrast in MacOS
Contrast Theme II
Nombres de colores I
Canvas / CanvasText (*): Background color / Regular text color
Link (*): Link color
ButtonFace / ButtonText (*): Button background color / Button text color
Field / FieldText
SelectedItem / SelectedItemText
AccentColor / AccentColorText
ActiveText / VisitedText
Highlight / HighlightText (*): Selected text background color / Selected text color
GrayText (*) (text color disabled)
Mark / MarkText
(*) Nombre de colores seguros y comunes
Nombres de colores II
See the Pen CSS4 System colors: forced-colors: active by Iván Albizu (@ivan_albizu) on CodePen.
Propiedades afectadas
color
background-color
text-decoration-color
text-emphasis-color
border-color
outline-color
column-rule-color
-webkit-tap-highlight-color
SVG fill attribute
SVG stroke attribute
Propiedades con comportamiento especial
box-shadow: forzado a 'none'
text-shadow: forzado a 'none'
background-image: forzado a 'none' excepto url-based
color-scheme: forzado a 'light dark'
scrollbar-color: forzado a 'auto'
Detectar preferencias de contraste - CSS @media
@media (forced-colors: active) {
.selector {
// +-equivale a "none" (currentColor, inherit)
// +info: https://developer.mozilla.org/en-US/docs/Web/CSS/forced-color-adjust#preserve-parent-color
forced-color-adjust: preserve-parent-color;
//forced-color-adjust: none; //Con firefox puede dar problemas
&__hijo {
forced-color-adjust: auto;
}
}
}
Detectar preferencias de contraste - Javascript
const forced_colors = matchMedia('(forced-colors: active)');
if ( forced_colors ) {
// User has constrast theme active
}
Y ahora... ejemplo
See the Pen Untitled by Iván Albizu (@ivan_albizu) on CodePen.
Y ahora... la chapa (I)
<a>Enlace</a><button>Botón</button>Y ahora... la chapa (II)
border-color: transparent;text-decoration-color: transparent; en lugar de text-decoration: none;media="(forced-colors: active)" en los <source> de <picture>Y ahora... ¿merece la pena?
Y ahora... recursos interesantes
Nombres accesibles (accName)
Accessibility tree - diagrama
Accessibility tree - contenido
| role |
<button> <link> [...]
|
| name |
Contenido
|
| description |
Contenido ayuda (exigencias para contraseñas)
|
| state |
checkbox (checked/unchecked)
button (pressed/unpressed) |
¿Qué es nombre accesible?
Importancia de accName (I)
Importancia de accName (II). Ejemplo
See the Pen Accessibility Content by Iván Albizu (@ivan_albizu) on CodePen.
Formas de establecer accName
See the Pen Accessibility CTA accName (II) by Iván Albizu (@ivan_albizu) on CodePen.
Orden en que se computa accName
aria-labelledby y apunta a id existenterole="presentation" o role="none"
title / alt<label> / <legend>WCAG (I)
WCAG (II)
EXTRA: accName Computations
| TAG | aria-labelledby |
aria-label |
alt |
<legend> |
title |
| <img> | 1 | 2 | 3 | NA | 4 |
| <figure> | 1 | 2 | 3 | NA | 4 |
| <iframe> | 1 | 2 | NA | NA | 3 |
| <fieldset> | 1 | 2 | NA | 3 | 4 |
| <header>, <main>, <nav>, <section> [...] | 1 | 2 | NA | NA | 3 |
| TAG | aria-labelledby |
aria-label |
<label> |
Content |
Value |
<legend> |
title |
placeholder |
| <a href=""> | 1 | 2 | NA | 3 | NA | NA | 4 | NA |
| <button> | 1 | 2 | 3 | 4 | NA | NA | 5 | NA |
| <input type="text|password|search|tel|email|url|number"> | 1 | 2 | 3 | NA | NA | NA | 4 | 5 |
| <input type="submit|reset"> | 1 | 2 | 3 | NA | 4 | 5: "submit" / "reset" | 6 | NA |
| <input type="button"> | 1 | 2 | 3 | NA | 4 | NA | 5 | NA |
EXTRA: popurri
Recursos interesantes
Astro
Astro - Islands
Astro - scaffolding I
Astro - scaffolding II
Astro - estructura de un fichero
---
import Layout from "../layouts/Layout.astro";
import ProductCard from "../components/ProductCard.astro";
interface Props {
title: string;
description: string;
}
const { title, description } = Astro.props;
---
[...]
Astro Transitions - ¿Qué es?
View Transitions API
Interceptar la navegación
Animar elementos de Página Destino con Página Destino
MDN: View_Transitions_APIAstro Transitions - old vs new
Astro Transitions - inicialización
src/pages/index.astro
---
import { ViewTransitions } from 'astro:transitions';
---
<html lang="en">
<head>
Title pages
</head>
<body>
Welcome to my website!
</body>
</html>
Astro Transitions - directivas
Astro Transitions - Ejemplos
Sin Astro
Youtube videosCons Astro
Discos de músicaAstro Integraciones - VUE
VUEEjemplo en VSCode
Estado actual - Caniuse
Advanced attr() - CSS I
content: attr(data-attr);
--something: attr(data-attr);
--something: attr(data-attr type(<color>));
--something: attr(data-attr type(<color>), tomato);
--something: attr(id type(<custom-ident>), tomato);
Advanced attr() - CSS II
Advanced attr() - PENs
attr() colorAdvanced attr() - Recursos interesantes
La función attr() rediseñada - Bramus