Descripción general
Una tarjeta agrupa un fragmento de contenido relacionado o una opción. Es un patrón visual, no un modelo semántico o de interacción fijo, por lo que debes preservar el significado del contenido y usar la interacción nativa que coincida con su propósito.
Lineamientos
Elige la semántica para el contenido y su interacción por separado:
- usa
<article>como la raíz de la tarjeta, independientemente de si se vincula a un destino o no; - usa un vínculo nativo para la navegación. Cuando toda la tarjeta es un destino, un solo vínculo puede unir el
<article>solo si la tarjeta no contiene otros elementos interactivos (a,button,input,select,textarea). - mantener los vínculos y botones para acciones independientes como controles nativos separados
- Usa un botón de selección o una casilla de verificación con un
<label>asociado, o unoptionen un<select>nativo, cuando la tarjeta sea una opción.
Mantén el contenido multimedia, el título, el contenido de apoyo y las acciones en un orden de origen significativo; no uses CSS order para contradecirlo (consulta Diseños de CSS y diseño responsivo).
Implementación
Mantén el lenguaje de marcado al mínimo y permite que los selectores CSS reconozcan cada región, de modo que las tarjetas simples sigan siendo simples y las tarjetas enriquecidas sigan siendo posibles. Una tarjeta tiene hasta cuatro regiones, en este orden de origen, y cualquiera de ellas se puede omitir. Las regiones son elementos secundarios directos de la tarjeta, no se agrupan en elementos de wrapper, como .card__body, lo que impide colocar y aplicar diseño a las regiones por selector. Una región con un solo elemento es ese elemento en sí, no unido: un párrafo solo es el <p>. Usa un wrapper solo cuando una región contenga varios elementos.
- Contenido multimedia: un elemento
<img>,<picture>,<video>o<svg>como primer elemento secundario. Agrega una clase.mediasolo al contenido hero arbitrario que no sea uno de esos elementos y nunca unas un<img>simple en un elemento.media. - Encabezado: un encabezado por sí solo. Usa
<hgroup>solo cuando el encabezado tenga un subtítulo o un eslogan, y<header>cuando la región tenga más que un título, como una firma o una insignia. Cuando la tarjeta tiene un destino principal, el vínculo se incluye en el encabezado. - Contenido: Un solo
<p>,<ul>o<dl>se destaca por sí solo. Cuando el contenido consta de varios elementos, como varios párrafos o un párrafo más una lista, agrúpalos en un<div>para que la región sea un solo elemento de cuadrícula. - Pie de página: Es un
<footer>que contiene acciones independientes como vínculos y botones nativos. Un vínculo "leer más" puede compartir la URL del vínculo del encabezado, pero debe tener un nombre de accesibilidad descriptivo que comience con el texto visible, usando texto oculto visualmente (por ejemplo,Read more<span> about poached eggs</span>), porque los vínculos "leer más" idénticos son ambiguos en la lista de vínculos de un lector de pantalla. No agregues otros vínculos de pie de página que repitan la URL del encabezado.
La tarjeta más simple es un <article> que contiene un encabezado y un párrafo. Elige el patrón de vínculo y acción que coincida con el comportamiento de la tarjeta; consulta Modelos de interacción.
En el caso de las imágenes o los videos de tarjetas que deben llenar un área de proporción fija, establece aspect-ratio y object-fit: cover en el propio <img> o <video> para que llene el área sin distorsión (es posible que se produzcan recortes). Usa el aspect-ratio de un contenedor .media solo para otro contenido hero. De lo contrario, conserva la proporción intrínseca del contenido multimedia. Proporciona un texto alternativo adecuado para las imágenes informativas y usa alt="" para las imágenes decorativas.
Adaptación al espacio disponible
Basa el diseño en el espacio disponible de la tarjeta, no en el viewport. Para adaptar los descendientes de la tarjeta (contenido multimedia, texto, acciones), haz que la tarjeta sea el contenedor de tamaño (container-type: inline-size) y escribe reglas de @container para sus elementos secundarios. Evita definir el tamaño desde el elemento superior de la cuadrícula o la lista: el ancho real de la tarjeta puede depender de la cantidad de columnas, los espacios, etcétera, lo que hace que los puntos de interrupción basados en el elemento superior sean ruidosos.
En un contenedor estrecho, apila las regiones en el orden de origen. En un contenedor ancho, coloca el contenido multimedia en una columna lateral junto a las otras regiones, pero solo para las tarjetas que tengan contenido multimedia: define el alcance de esas reglas con :has() en el elemento secundario de contenido multimedia (por ejemplo, .card:has(> img)) para que las definiciones de columnas y las ubicaciones de grid-column nunca se apliquen a una tarjeta sin contenido multimedia. Una tarjeta sin contenido multimedia permanece en una sola columna en todos los anchos y no debe reservar una columna de contenido multimedia vacía.
Alinear tarjetas en una cuadrícula
Cuando las tarjetas de una fila deban compartir las alturas de sus regiones, usa subgrid: haz que cada tarjeta abarque cuatro pistas de fila compartidas (contenido multimedia, encabezado, contenido, pie de página) y coloca las regiones por selector de elementos, tratando todo lo que no sea contenido multimedia, un encabezado o un <footer> como contenido. Una tarjeta que omite una región deja su pista vacía, por lo que las regiones restantes se alinean con las tarjetas vecinas. Cada pista contiene un elemento de cuadrícula, por lo que debes unir la región de contenido en un <div> solo cuando tenga más de un elemento y las tarjetas compartan pistas. Las tarjetas que no están alineadas con elementos hermanos no necesitan un wrapper ni una subcuadrícula.
Modelos de interacción
Tarjetas de contenido
Usa un <article> como raíz de la tarjeta. Mantén los vínculos y los botones como controles nativos independientes.
Tarjetas de un solo destino
Cuando toda la tarjeta es un destino y no tiene acciones independientes, usa un vínculo nativo. El vínculo puede unir el <article>. No anides otros vínculos, botones ni controles de formulario dentro del vínculo, y mantén cualquier texto de "leer más" como un <p> o <span> simple. Como el nombre de accesibilidad del vínculo es todo el texto de la tarjeta, mantén el contenido breve. Si la tarjeta tiene mucho texto o incluye otras acciones, usa el patrón de vínculo estirado que se muestra a continuación para que solo el encabezado sea el vínculo:
<a href="/recipes/poached-eggs">
<article class="card">
<h3>Poached eggs</h3>
<p>Two poached eggs served on toasted sourdough.</p>
</article>
</a>
Tarjetas en las que se puede hacer clic con acciones independientes
Si al hacer clic en la tarjeta se activa una acción en lugar de navegar, usa un <button> en lugar de un vínculo.
Cuando una tarjeta de contenido se vincula a un destino principal, también contiene otros elementos interactivos y debe poder hacerse clic en ella en su totalidad:
- Usa una sola habilitación en el vínculo principal: coloca
.card-linken exactamente un vínculo por tarjeta (el vínculo del encabezado). El pie de página y otros vínculos nunca lo obtienen, o cada uno estiraría su propia superposición y el último capturaría toda la tarjeta. - Vincula su título y extiende el área de clic del puntero por toda la tarjeta con
::after
.card:has(a.card-link) {
position: relative;
}
.card a.card-link::after {
content: "";
position: absolute;
inset: 0;
}
- Eleva los elementos interactivos con
position: relative; z-index: 1para que sigan funcionando. Segmenta tipos de elementos (p.ej.,a, button) en lugar de requerir la habilitación a través de clases. - NO apliques
z-indexa contenedores enteros, ya que eso haría que capturen eventos de puntero que no producen ninguna acción.
.card:has(a.card-link) {
/* Keep other interactive elements above the overlay */
a:not(.card-link), button, input, x-button {
position: relative;
z-index: 1;
}
}
- Aplica diseño a la tarjeta en sí cuando se coloque el cursor sobre ella o se enfoque, en lugar de al vínculo estirado:
.card {
a.card-link {
&:focus-visible {
outline: none; /* Draw it on the card instead */
}
}
&:has(a.card-link:focus-visible) {
/* Focus ring */
}
&:has(a.card-link:hover) {
/* Hover styles */
}
}
Tarjetas de opciones
En el caso de las tarjetas que representan opciones predefinidas, usa <label class="card"> con una casilla de verificación o un botón de selección como elemento secundario directo.
Aplica el estilo :has(:checked) a la tarjeta seleccionada. Nunca cambies las propiedades que afectan el diseño, como border-width, padding o font-weight, en la selección, ya que la tarjeta y sus vecinas saltan. Enfatiza con outline, box-shadow o un borde transparente que solo cambie de color:
.card {
border: 2px solid transparent;
&:has(> :checked) {
border-color: var(--accent);
}
}
La casilla de verificación o el botón de selección visibles son, en sí mismos, un indicador de selección que no depende del color, por lo que el cambio de color por sí solo es suficiente. Si el control está oculto visualmente (mantenlo enfocable y en el árbol de accesibilidad, nunca display: none), agrega un indicador sin color que no afecte el diseño, como un ícono de marca de verificación o un outline más grueso.
Cuando las opciones pertenecen a un selector desplegable cuyas opciones se presentan como tarjetas, usa un elemento <select> nativo con appearance: base-select y aplica diseño a los elementos ::picker(select) y <option> en lugar de reemplazar la selección por tarjetas <div>. Consulta Diseños de selectores personalizados para obtener más detalles y alternativas.