Con la calcomanía “I Voted” de California en CSS para el día de las elecciones 2018 | Programar Plus

Oh, oye, mañana (¡mañana!) Es el día de las elecciones aquí en los Estados Unidos. No estamos en el negocio de hacer respaldos políticos ni nada por el estilo en CSS-Tricks, aunque respaldamos que todos ejerzan su derecho al voto.

Hice exactamente eso hace dos años y publiqué una versión CSS de la calcomanía “Yo voté” que venía con mi boleta de votación por correo de California.

Vea la etiqueta Pen I Voted de Geoff Graham (@geoffgraham) en CodePen.

Avance rápido hasta hoy, y recibí una nueva calcomanía en la boleta con un diseño nuevo:

Crédito: Revista Los Ángeles (fuente)

Tengo un poco de tiempo, así que intentaré volver a crear esta pegatina en CSS y repasar mi proceso de pensamiento mientras lo hago. ¡No dudes en seguirnos si quieres!

Rompiendo los elementos

Cada vez que me dan un diseño de cualquier tipo, me gusta fingir que mis ojos tienen el superpoder de la visión de rayos X y pueden ver a través del diseño como si fuera un esqueleto. Esto me ayuda a comenzar a pensar en cuántos elementos podría usar en el HTML.

Bien, creo que voy a empezar con algo como esto:

<!-- Main Circle -->
<div class="sticker">
  <div class="sticker__top">
    <!-- Will use ::before and ::after to create halves -->
    <h1>I Voted</h1>
  </div>
  <div class="sticker__bottom">
    <!-- The list of languages -->
    <ul>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
    </ul>
  </div>
</div>

También voy a incluir algunos estilos básicos en el <body> para que pueda saltar directamente al resto de la pegatina.

Consulte el HTML de la etiqueta “I Voted” de la pluma de Geoff Graham (@geoffgraham) en CodePen.

OK, nada lujoso hasta ahora. Realmente parece una lista desordenada con un título con un terrible contraste entre el contenido y el fondo.

Trabajando en el contenedor de pegatinas principal

Creo que prepararé el contenedor, que es el círculo principal. Voy a usar un ancho y un alto fijos, luego usaré border-radius para redondearlo y darle la forma de un círculo.

Ah, y debería ocuparme de ese texto oscuro y también agregar un borde mientras estoy en eso, para poder ver lo que estoy haciendo.

.sticker {
   border: 20px solid #fff;
   border-radius: 100%;
   color: #fff;
   height: 400px;
   width: 400px;
 }

Consulte el HTML 2 de la etiqueta “I Voted” de la pluma de Geoff Graham (@geoffgraham) en CodePen.

La alineación está fuera de lugar. Parece un buen lugar para dejarse caer en algún flexbox. Esto me permitirá centrar nuestros elementos horizontalmente. Creo que ir con un diseño de una sola columna se encargará de la alineación vertical.

.sticker {
  display: flex;
  flex-flow: column;
  align-items: center;
  border: 20px solid #fff;
  border-radius: 100%;
  color: #fff;
  height: 400px;
  width: 400px;
}

Sí, eso ayuda.

Consulte la pegatina HTML 3 de Pen “I Voted” de Geoff Graham (@geoffgraham) en CodePen.

Lo último que quiero hacer con la pegatina por ahora es dividirla en dos mitades: una superior y una inferior. OK, entonces sí, tengo elementos explícitos para aquellos en el HTML (.sticker__top y .sticker__bottom). Podría usar background-color en cada elemento para hacer que la mitad superior sea azul y la mitad inferior roja, pero en realidad me gusta la idea de usar un degradado lineal en su lugar con una parada brusca en la marca a mitad de camino.

.sticker {
  background-image:
    linear-gradient(
      to bottom,
       #080968,
       #080968 50%,
       #080968 50%,
       #F81616 50%
    );
  border: 20px solid #fff;
  border-radius: 100%;
  color: #fff;
  display: flex;
  flex-flow: column;
  align-items: center;
  height: 400px;
  width: 400px;
}

¡Oye ahora, luciendo mucho más nítido ya!

Consulte la calcomanía HTML 4 de Pen “I Voted” de Geoff Graham (@geoffgraham) en CodePen.

Es hora de lidiar con la mitad superior

Las mitades superior e inferior ocupan el 50% de la altura de la pegatina, por lo que los selectores se pueden combinar para golpearlos a ambos a la vez. Además, estoy usando flexbox, por lo que simplemente puedo flexionar esos elementos.

.sticker__top,
.sticker-bottom {
  flex: 0 50%;
}

La mitad superior es muy extraña. A mi modo de ver, hay dos filas: una que contiene las barras y estrellas y la otra que contiene el encabezado. Voy a recurrir a flexbox nuevamente para dibujar ese diseño.

.sticker__top {
  display: flex;
  flex-flow: row wrap;
  position: relative;
}

Eso no va a cambiar mucho en este momento porque, bueno, no he hecho nada para definir elementos para las barras y estrellas en el HTML. Estoy pensando en usar el ::before y ::after pseudo elementos en .sticker__top para hacer esos. Nuevamente, se pueden combinar ya que comparten algunas propiedades y valores comunes.

.sticker__top::before,
.sticker__top::after {
  content: "";
  height: 45%; /* Had to play with this a bit */
  margin-top: 2em; /* Move away from the top edge of the sticker */
}

Voy a hacer trampa y usar SVG para las estrellas. Quiero decir, supongo que eso no es una trampa, pero se siente como una desviación de la forma “pura” de hacer las cosas con CSS. Oh bien.

Dicho esto, las rayas definitivamente se pueden hacer en CSS, nuevamente, con la misma técnica de fondo de degradado lineal que se usa para dividir la etiqueta en mitades azul y roja.

.sticker__top::before {
  background-image: 
    url("/path/to/star/image.svg");
  background-size: 35px; /* Magic number, depends on the image used. */
}

.sticker__top::after {
  background-image:
    linear-gradient(
      to bottom,
          #F81616,
          #F81616 14%,
      transparent 14%,
      transparent 28%,
          #F81616 28%,
          #F81616 42%,
      transparent 42%,
      transparent 56%,
          #F81616 56%,
          #F81616 70%,
      transparent 70%,
      transparent 84%,
          #F81616 84%,
          #F81616 98%,
      transparent 100%
    );
}

Eso es genial pero, mierda, las cosas están fuera de orden.

Consulte la pegatina HTML 5 de Pen “I Voted” de Geoff Graham (@geoffgraham) en CodePen.

Estoy muy agradecido de que Flexbox tenga un order propiedad. Voy a ordenar las estrellas, rayas y rumbo en 1, 2 y 3, respectivamente,

.sticker__top::before {
  /* Same as before... */
  order: 1;
}

.sticker__top::after {
  /* Same as before... */
  order: 2;
}

.sticker__top h1 {
  order: 3;
}

Si me detengo aquí, la forma de las barras y estrellas se desvanecerá y la fuente del título será descuidada.

border-radius sigue siendo una buena forma de conseguir que las barras y estrellas sigan la misma trayectoria circular que la pegatina. El problema es que la parte inferior de ellos debe mantener un borde plano. Ya que border-radius es una propiedad taquigráfica, voy a soltar border-top-left-radius en las estrellas y border-top-right-radius en las rayas.

También vale la pena señalar que las rayas son un poco más anchas que las estrellas. ¿Quizás una división de 55-45? No sé. Iré con eso y también usaré el posicionamiento relativo en las rayas para poder empujarlas un poco hacia la derecha para agregar separación entre ellas y las estrellas.

.sticker__top::before {
  /* Same as before... */
  flex: 45%;
}
  
.sticker__top::after {
  /* Same as before... */
  flex: 55%;
  position: relative;
  left: 10px;
}

Las estrellas y rayas deben flexionarse con el tamaño y el ancho del título. Tuve que jugar con la familia de fuentes, el tamaño de fuente, el espaciado entre letras y la transformación del texto para obtener algo que se vea bastante bien. En caso de que se lo pregunte, terminé usando Raleway para la fuente. No es preciso, pero lo suficientemente cercano … al menos para mi ojo tipográfico inexperto.

.sticker__top h1 {
  font-family: 'Raleway', sans-serif;
  font-size: 4em;
  letter-spacing: 3px;
  line-height: 0;
  text-transform: uppercase;
  order: 3;
}

Vea la calcomanía HTML 6 de Pen “I Voted” de Geoff Graham (@geoffgraham) en CodePen.

Muy bien, ahora la mitad inferior me pone la piel de gallina. Tengo que abordar eso.

Dale estilo a la mitad inferior

Ya se ha hecho mucho. El elemento de la mitad inferior ya está en el HTML y tiene el tamaño y la posición que debería tener. Creo que eliminar las viñetas de los elementos de la lista y eliminar el relleno izquierdo de la lista desordenada limpiará mucho las cosas.

.sticker__bottom ul {
  list-style: none;
  padding: 0;
  width: 100%; /* Gotta take up the all of the bottom half */
}

Pero eso no lo va a cortar por completo. Quiero que la lista se ejecute horizontalmente, ajuste las líneas y permita que los elementos de la lista ocupen un espacio abierto. Sí, eso suena a flexbox de nuevo.

.sticker__bottom ul {
  display: flex;
  flex-flow: row wrap;
  align-items: flex-start;
  justify-content: flex-start;
  /* same as before... */
}

.sticker__bottom li {
  flex: auto; /* Flex as much as you need, guys */
  margin: .75em; /* A liiiiitle breathing room between items */
}

Consulte la pegatina HTML 7 de Pen “I Voted” de Geoff Graham (@geoffgraham) en CodePen.

Ahora tengo que hacer algunos ajustes para .sticker__bottom. Específicamente, lo haré un poco más estrecho (80% del ancho total de la etiqueta) para sacarlo del borde de la etiqueta y luego redondear sus bordes … aunque es posible que no necesite esquinas redondeadas ya que el contenido no va a Desbordamiento.

.sticker__bottom {
  border-bottom-right-radius: 100%;
  border-bottom-left-radius: 100%;
  width: 80%;
}

Y ahora centra el texto. Supongo que eso puede pasar con el padre .sticker elemento ya que nada en la etiqueta está técnicamente justificado a la izquierda.

.sticker {
  /* same as before... */
  text-align: center;
}

Finalmente, haré todo lo posible para reemplazar el contenido ficticio con las traducciones de “Yo voté”. Déjame ir a buscarlos.

(Dirígete al Traductor de Google).

Meh, no pude encontrar todo lo que necesitaba. Estoy seguro de que es mi falta de paciencia, pero terminé usando algunas alternativas:

<ul>
  <li>Yo voté</li>
  <li>我投票</li>
  <li>나는 투표했다</li>
  <li>Bumoto ako</li>
  <li>Я проголосував</li>
  <li>मैने मतदान किया</li>
  <li>أنا صوتت</li>
  <li>Ik stemde</li>
  <li>Szavaztam</li>
  <li>ฉันโหวตแล้ว</li>
  <li>Anigu waxaan codsaday</li>
  <li>Tôi đã bầu chọn</li>
</ul>

Voy a tener que jugar con el tamaño de la fuente y conseguir el mismo tipo de alineación que la pegatina IRL, que tiene filas de: 4 elementos, 3 elementos, 3 elementos, 1 elemento, 1 elemento.

Aquí es donde aterricé:

.sticker__bottom ul {
  display: flex;
  flex-flow: row wrap;
  font-size: .75em;
  align-items: flex-start;
  justify-content: flex-start;
  list-style: none;
  padding: 0;
  width: 100%;
}

Para sacar los dos últimos elementos de la misma línea, voy a destacar el penúltimo usando :last-child() para que ambos se flexionen siempre al 100%:

.sticker__bottom li:nth-child(11) {
  flex: 100%;
}

Y, por último, voy a cambiar el borde blanco alrededor de la pegatina de blanco a azul. Le da ese acolchado falso que estamos buscando.

Consulte la pegatina HTML 8 de Pen “I Voted” de Geoff Graham (@geoffgraham) en CodePen.

¡Ding, listo!

Voy a llamar a este horneado. Sé que sé. Debería probarlo en varios navegadores. También sería prudente encontrar alternativas elegantes para los navegadores más antiguos que no admitan flexbox. Y sería bueno tener cierta capacidad de respuesta. Quizás a alguien le gustaría tomarlos y compartirlos. 😉

¿Es esta la mejor forma de hacer la pegatina? Probablemente no. Por ejemplo, apuesto a que hay algunas cosas interesantes que se pueden hacer con clip-path en lugar de la forma en que busqué a tientas a través de los degradados de fondo. Y, si tuviera que hacerlo de nuevo, incluso podría considerar usar un diseño CSS Grid en el padre porque claramente hay oportunidades para trabajar en dos direcciones en lugar de una.

Pero esa es la belleza de CSS. Hay más de una forma de lograr algo.

Feliz día de las elecciones, amigos. 🇺🇸