Cree una nube de etiquetas con CSS simple e incluso JavaScript más simple

Siempre me han gustado las nubes de etiquetas. Me gusta la experiencia de usuario de ver qué etiquetas son más populares en un sitio web al ver el tamaño de fuente relativo de las etiquetas, ya que las etiquetas populares son más grandes. Parecen haber pasado de moda, aunque a menudo se ven versiones de ellos utilizadas en ilustraciones en herramientas como Wordle .

¿Qué tan difícil es hacer una nube de etiquetas? No es nada difícil. ¡Vamos a ver!

Empecemos con el marcado.

Para nuestro HTML, colocaremos cada una de nuestras etiquetas en una lista, ulul. Lo inyectaremos con JavaScript.

Si su nube de etiquetas ya está en HTML y solo está buscando hacer lo relativo font-size, ¡eso es bueno! ¡Mejora progresiva! Debería poder adaptar JavaScript más adelante para que haga solo esa parte, pero no necesariamente cree e inyecte las etiquetas en sí.

Me he burlado de algunos JSON con una cierta cantidad de artículos etiquetados con cada propiedad. Escribamos algo de JavaScript para tomar ese feed JSON y hacer tres cosas.

Primero, crearemos un archivo lia partir de cada entrada de nuestra lista. Imagina que el HTML, hasta ahora, es así:

ul  lialign-content/li  lialign-items/li  lialign-self/li  lianimation/li  li.../li  liz-index/li/ul

En segundo lugar, pondremos la cantidad de artículos que tiene cada propiedad entre paréntesis al lado de cada elemento de la lista. Ahora, el marcado es así:

ul  lialign-content (2)/li  lialign-items (2)/li  lialign-self (2)/li  lianimation (9)/li  li.../li  liz-index (4)/li/ul

En tercer y último lugar, crearemos un vínculo alrededor de cada etiqueta que vaya al lugar correcto. Aquí es donde podemos establecer la font-sizepropiedad para cada elemento dependiendo de con cuántos artículos esté etiquetada esa propiedad, de modo animationque tener 13 artículos será mucho más grande que background-colortener solo un artículo.

li  a       href="https://example.com/tags/animation"       animation (9)  /a/li

La parte de JavaScript

Echemos un vistazo al JavaScript para hacer esto.

const dataURL =  "https://gist.githubusercontent.com/markconroy/536228ed416a551de8852b74615e55dd/raw/9b96c9049b10e7e18ee922b4caf9167acb4efdd6/tags.json";const tags = document.querySelector(".tags");const fragment = document.createDocumentFragment();const maxFontSizeForTag = 6;fetch(dataURL)  .then(function (res) {    return res.json();  })  .then(function (data) {    // 1. Create a new array from data    let orderedData = data.map((x) = x);    // 2. Order it by number of articles each tag has    orderedData.sort(function(a, b) {      return a.tagged_articles.length - b.tagged_articles.length;    });    orderedData = orderedData.reverse();    // 3. Get a value for the tag with the most articles    const highestValue = orderedData[0].tagged_articles.length;    // 4. Create a list item for each result from data.    data.forEach((result) = handleResult(result, highestValue));    // 5. Append the full list of tags to the tags element    tags.appendChild(tag);  });

El JavaScript anterior utiliza la API Fetch para fetchla URL donde tags.jsonestá alojado. Una vez que obtiene estos datos, los devuelve como JSON. Aquí realizamos una secuencia en una nueva matriz llamada orderedData(para no mutar la matriz original), encontramos la etiqueta con la mayor cantidad de artículos. Usaremos este valor más adelante en una escala de fuente para que todas las demás etiquetas tengan un tamaño de fuente relativo a él. Luego, forEachcomo resultado de la respuesta, llamamos a una función que he nombrado handleResult()y pasamos resulty highestValuea esta función como parámetro. También crea:

  • una variable llamada tagsque es la que usaremos para inyectar cada elemento de la lista que creamos a partir de los resultados,
  • una variable para que a fragmentcontenga el resultado de cada iteración del bucle, que luego agregaremos al tags, y
  • una variable para el tamaño máximo de fuente, que usaremos en nuestra escala de fuente más adelante.

A continuación, la handleResult(result)función:

function handleResult(result, highestValue) {  const tag = document.createElement("li");  tag.classList.add("tag");  tag.innerHTML = `a href="${result.href}"token interpolation"${result.tagged_articles.length * 1.25}em"${result.title} (${result.tagged_articles.length})/a`;  // Append each tag to the fragment  fragment.appendChild(tag);}

Esta es una función bastante simple que crea un elemento de lista establecido en la variable nombrada tagy luego agrega una .tagclase a este elemento de lista. Una vez creado, configura el innerHTMLelemento de la lista como un enlace y completa los valores de ese enlace con valores del feed JSON, como un result.hrefpara el enlace a la etiqueta. Cuando lise crea cada uno, se agrega como una cadena al archivo fragment, que luego agregaremos a la tagsvariable. El elemento más importante aquí es la styleetiqueta en línea que utiliza la cantidad de artículos result.tagged_articles.lengthpara establecer un tamaño de fuente relativo usando emunidades para este elemento de la lista. Más adelante, cambiaremos ese valor a una fórmula para usar una escala de fuente básica.

Encuentro este JavaScript un poco feo y duro a la vista, así que creemos algunas variables y una fórmula de escala de fuente simple para cada una de nuestras propiedades para ordenarlo y hacerlo más fácil de leer.

function handleResult(result, highestValue) {  // Set our variables  const name = result.title;  const link = result.href;  const numberOfArticles = result.tagged_articles.length;  let fontSize = numberOfArticles / highestValue * maxFontSizeForTag;  fontSize = +fontSize.toFixed(2);  const fontSizeProperty = `${fontSize}em`;  // Create a list element for each tag and inline the font size  const tag = document.createElement("li");  tag.classList.add("tag");  tag.innerHTML = `a href="${link}"token interpolation"${fontSizeProperty}"${name} (${numberOfArticles})/a`;    // Append each tag to the fragment  fragment.appendChild(tag);}

Al establecer algunas variables antes de comenzar a crear nuestro HTML, el código es mucho más fácil de leer. Y también hace que nuestro código sea un poco más SECO, ya que podemos usar la numberOfArticlesvariable en más de un lugar.

Una vez que cada una de las etiquetas se ha devuelto en este .forEachbucle, se recopilan juntas en el archivo fragment. Después de eso, usamos appendChild()para agregarlos al tagselemento. Esto significa que el DOM se manipula solo una vez, en lugar de manipularlo cada vez que se ejecuta el bucle, lo que supone una buena mejora del rendimiento si tenemos una gran cantidad de etiquetas.

Escala de fuente

Lo que tenemos ahora funcionará bien para nosotros y podríamos comenzar a escribir nuestro CSS. Sin embargo, nuestra fórmula para la fontSizevariable significa que la etiqueta con más artículos (que es “flex” con 25) será 6em (25 / 25 * 6 = 6), pero las etiquetas con un solo artículo van a ser 1/ 25 del tamaño de eso (1/25 * 6 = 0,24), lo que hace que el contenido sea ilegible. Si tuviéramos una etiqueta con 100 artículos, a las etiquetas más pequeñas les iría aún peor (1/100 * 6 = 0,06).

Para solucionar esto, agregué una ifdeclaración simple de que iflo fontSizeque se devuelve es menor que 1, configúrelo fontSizeen 1. Si no, manténgalo en su tamaño actual. Ahora, todas las etiquetas estarán dentro de una escala de fuente de 1em a 6em, redondeada a dos decimales. Para aumentar el tamaño de la etiqueta más grande, simplemente cambie el valor de maxFontSizeForTag. Puede decidir qué funciona mejor para usted según la cantidad de contenido con el que esté tratando.

function handleResult(result, highestValue) {  // Set our variables  const numberOfArticles = result.tagged_articles.length;  const name = result.title;  const link = result.href;  let fontSize = numberOfArticles / highestValue * maxFontSizeForTag;  fontSize = +fontSize.toFixed(2);    // Make sure our font size will be at least 1em  if (fontSize = 1) {    fontSize = 1;  } else {    fontSize = fontSize;  }  const fontSizeProperty = `${fontSize}em`;    // Then, create a list element for each tag and inline the font size.  tag = document.createElement("li");  tag.classList.add("tag");  tag.innerHTML = `a href="${link}"token interpolation"${fontSizeProperty}"${name} (${numberOfArticles})/a`;  // Append each tag to the fragment  fragment.appendChild(tag);}

¡Ahora el CSS!

Estamos usando flexbox para nuestro diseño ya que cada una de las etiquetas puede tener un ancho variable. Luego los alineamos en el centro justify-content: centery eliminamos las viñetas de la lista.

.tags {  display: flex;  flex-wrap: wrap;  justify-content: center;  max-width: 960px;  margin: auto;  padding: 2rem 0 1rem;  list-style: none;  border: 2px solid white;  border-radius: 5px;}

También usaremos flexbox para las etiquetas individuales. Esto nos permite alinearlos verticalmente, align-items: centerya que tendrán diferentes alturas según el tamaño de fuente.

.tag {  display: flex;  align-items: center;  margin: 0.25rem 1rem;}

Cada enlace en la nube de etiquetas tiene un poco de relleno, solo para permitir que se pueda hacer clic en él ligeramente fuera de sus dimensiones estrictas.

.tag__link {  padding: 5px 5px 0;  transition: 0.3s;  text-decoration: none;}

Encuentro que esto es útil en pantallas pequeñas, especialmente para las personas a las que les puede resultar más difícil tocar enlaces. La inicial text-decorationse elimina porque creo que podemos asumir que cada elemento de texto en la nube de etiquetas es un enlace y, por lo tanto, no se necesita una decoración especial para ellos.

Simplemente agregaré algunos colores para darle estilo un poco más a las cosas:

.tag:nth-of-type(4n+1) .tag__link {  color: #ffd560;}.tag:nth-of-type(4n+2) .tag__link {  color: #ee4266;}.tag:nth-of-type(4n+3) .tag__link {  color: #9e88f7;}.tag:nth-of-type(4n+4) .tag__link {  color: #54d0ff;}

El esquema de color para esto fue robado directamente del blogroll de Chris , donde cada cuarta etiqueta que comienza en la etiqueta uno es amarilla, cada cuarta etiqueta que comienza en la etiqueta dos es roja, cada cuarta etiqueta que comienza en la etiqueta tres es violeta. y cada cuarta etiqueta que comienza en la etiqueta cuatro es azul.

Luego configuramos los estados de enfoque y desplazamiento para cada enlace:

.tag:nth-of-type(4n+1) .tag__link:focus,.tag:nth-of-type(4n+1) .tag__link:hover {  box-shadow: inset 0 -1.3em 0 0 #ffd560;}.tag:nth-of-type(4n+2) .tag__link:focus,.tag:nth-of-type(4n+2) .tag__link:hover {  box-shadow: inset 0 -1.3em 0 0 #ee4266;}.tag:nth-of-type(4n+3) .tag__link:focus,.tag:nth-of-type(4n+3) .tag__link:hover {  box-shadow: inset 0 -1.3em 0 0 #9e88f7;}.tag:nth-of-type(4n+4) .tag__link:focus,.tag:nth-of-type(4n+4) .tag__link:hover {  box-shadow: inset 0 -1.3em 0 0 #54d0ff;}

Probablemente podría haber creado una variable personalizada para los colores en esta etapa (como --yellow: #ffd560, etc.), pero decidí optar por el enfoque manual para la compatibilidad con IE 11. Me encanta el box-shadowefecto de desplazamiento. Es una cantidad muy pequeña de código para lograr algo mucho más atractivo visualmente que un subrayado estándar o un borde inferior. Usar emunidades aquí significa que tenemos un control decente sobre el tamaño de la sombra en relación con el texto que necesitaba cubrir.

Bien, completemos esto configurando cada enlace de etiqueta para que sea negro al pasar el mouse:

.tag:nth-of-type(4n+1) .tag__link:focus,.tag:nth-of-type(4n+1) .tag__link:hover,.tag:nth-of-type(4n+2) .tag__link:focus,.tag:nth-of-type(4n+2) .tag__link:hover,.tag:nth-of-type(4n+3) .tag__link:focus,.tag:nth-of-type(4n+3) .tag__link:hover,.tag:nth-of-type(4n+4) .tag__link:focus,.tag:nth-of-type(4n+4) .tag__link:hover {  color: black;}

¡Y hemos terminado! Aquí está el resultado final:

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir