¿Qué tan bien conoces CSS? (+ mini-prueba)

imagen

La diferencia entre el uso exitoso de CSS y los intentos dolorosos de tratarlo a menudo depende de pequeños detalles. De hecho, CSS tiene muchos matices. Una de las áreas más comunes donde a menudo noto tal lucha es el diseño de estilos. Personalmente, me gusta aprender patrones CSS. Noté que tiendo a usar un pequeño número de ellos para resolver la mayoría de los problemas con el diseño. Este artículo trata sobre esos patrones CSS que uso para superar los problemas de diseño. Se considerarán las situaciones independientemente de la metodología CSS utilizada: ya sea SMACSS, BEM o incluso un tema candente de CSS-in-JS, porque todas se centran en las propiedades CSS en sí mismas, y no en la arquitectura, organización o estrategia.



Por diversión, comencemos con la prueba.


Utilizaremos la plataforma que desarrollé, llamada Questionable.io, y la utilicé para crear una prueba, que seguiremos a continuación. No se preocupe, no se recopilan datos personales, los resultados son anónimos y es totalmente gratuito.

El propósito de las pruebas es ver si puede reconocer un comportamiento CSS específico y algunos problemas sin leer primero el artículo. No iba a dificultar las pruebas, pero los matices del estilo CSS pueden ser bastante complicados. Recuerde, esta prueba es solo por diversión. Los resultados de la prueba no demuestran su frescura, pero espero que sigan siendo útiles.

El examen consta de 10 preguntas y no debe tomar más de 10 minutos.
Del traductor:

Al final del artículo sobre Habr, se agrega una encuesta sobre el número de puntos obtenidos en la prueba.

Pasar la prueba


Nota: si no desea perder el tiempo, aquí hay un enlace a preguntas con las respuestas correctas.

¿Pasaste la prueba? Genial Repasemos las preguntas una por una para tener una mejor idea de los patrones de estilo que se ven afectados en la prueba.

Pregunta 1: Modelo de bloque


Estudiar el modelo de bloque debería ser una prioridad en la lista de cualquier desarrollador de FrontEnd. Tal vez el artículo " El modelo CSS Box " es un poco antiguo, no subestimes su valor y relevancia para el CSS moderno. El modelo de bloque es la base de casi todos los problemas relacionados con los diseños CSS.

Esta pregunta particular verifica cómo averiguar el ancho basado en los principios del modelo de bloques. Un bloque tiene un ancho explícito a través de la width: 100px , pero resulta que las reglas predeterminadas del modelo de bloque aplican las propiedades de width a la capa de "contenido" de este bloque. El ancho resultante (qué tan ancho se dibuja el bloque en la página) es la suma del contenido, el relleno y las capas de borde. Por esta razón, la respuesta es 112px.

 .box { width: 100px; /* Take this */ height: 50px; padding: 5px; /* Plus this x2 for left and right */ border: 1px solid red; /* Plus this x2 for left and right */ background-color: red; /* = 112px of computed width */ } 

Si se enfrenta a una situación en la que la última columna o pestaña de la interfaz se mueve hacia abajo a la siguiente línea, aunque especificó para todo el width: 20%; y estaban seguros de que encajarían en el 100% del elemento padre, probablemente esto se estaba convirtiendo en un problema. Cinco columnas con un ancho del 20% se colocan en el 100%, pero si se les da adicionalmente relleno y / o borde, esto aumentará el ancho de cada una, dejando poco espacio en la fila actual para la última columna.

Cuando se introdujo CSS3, box-sizing una nueva herramienta llamada box-sizing . Nos permite controlar a qué capa del modelo de bloque queremos aplicar la propiedad de width . Por ejemplo, podemos especificar box-sizing: border-box . Esto significa que queremos que las reglas de ancho se apliquen a la capa del borde exterior en lugar de la capa de contenido. En la pregunta de la prueba, si se aplicó la propiedad box-sizing: border-box , el ancho del bloque resultante fue de 100 px.

Para algunos de ustedes, este es un hecho bien conocido, pero aún así será un buen recordatorio tanto para profesionales como para principiantes.

Hay una serie de artículos sobre el modelo de bloque y cómo usar la propiedad de tamaño de caja como un reinicio para aplicarlo inmediatamente a todo el proyecto. Tamaño de la caja y heredando el tamaño de la caja Probablemente, las mejores prácticas son dos buenos artículos de CSS-Tricks para leer.

Pregunta 2: límites de elementos


La segunda pregunta de la prueba puede verse parcialmente como una continuación de la primera. Recuerde, una cosa es leer: "El modelo de bloque tiene capas (contenido, relleno, borde) y todas ellas afectan el ancho y la altura total del elemento", otra cosa es poder reconocer los problemas del modelo de bloque en una situación real. Este problema en particular es un poco clásico entre aquellos que han estado trabajando con CSS por algún tiempo. Se deduce del hecho de que los marcos ocuparán un cierto espacio adicional y alejarán los elementos circundantes, ya que son parte del modelo de bloque. Agregar marcos mientras se cambia el estado de un elemento, como :hover , significará que los bloques se harán más grandes y luego los bloques que siguen serán empujados hacia abajo. Esto puede ser molesto :


De todas las posibles soluciones mencionadas en la pregunta de la prueba, agregar border: 2px solid transparent al estado original (sin desplazarse) es la única solución posible al problema. box-sizing no resuelve este problema, porque no establecemos explícitamente la altura. Si hiciéramos esto, el marco se convertiría en parte de la altura total del elemento y el cambio no ocurriría, pero este no es nuestro caso.

Hay otras soluciones que no mencionamos en las opciones de respuesta. Uno de ellos es agregar un pseudo-borde usando la propiedad box-shadow o usando el outline lugar del border . Cada uno de ellos no dará lugar a sesgo, ya que no es una capa del modelo de bloque. Aquí hay otro artículo de CSS-Tricks donde puedes leer más sobre tales soluciones.

Nota:
Recuerde que el outline no admite border-radius

Pregunta 3: Posicionamiento - absoluto vs fijo


Además de comprender cuándo usar cada uno de los tipos y cómo difieren en la representación visual , también es muy importante conocer las reglas de cómo cada uno de los métodos de posicionamiento está vinculado al elemento padre utilizando las propiedades superior, derecha, inferior o izquierda.

En primer lugar, veamos el bloque contenedor . Una breve definición es que el bloque contenedor suele ser el padre de cualquier elemento en cuestión. Sin embargo, las reglas para el bloque contenedor son diferentes para elementos posicionados de manera absoluta y fija.

1) Para elementos absolutos . El bloque contenedor es el ancestro más cercano cuyo posicionamiento no es static . Por ejemplo, cuando un elemento está en una posición absoluta y contiene las propiedades top , right , bottom o left , se colocarán en relación con cualquier elemento primario que tenga una posición absolute , relative , fixed o fixed .
2) Para elementos fijos . El bloque contenedor es la ventana gráfica, a pesar de la presencia de elementos principales con un posicionamiento que no sea static . Además, el comportamiento del desplazamiento es diferente de los elementos posicionados absolutamente. Los elementos fijos permanecen "fijos" en el área de visualización, de ahí el nombre.

Muchos desarrolladores piensan que los elementos posicionados absolutamente solo buscan el elemento padre más cercano con una posición de position: relative . Este concepto erróneo se ha generalizado simplemente porque position: relative especifica con mayor frecuencia emparejado con position: absolute para crear un bloque contenedor. La razón por la que esto se usa a menudo es que la posición relativa del bloque principal lo deja en la secuencia , lo que a menudo se prefiere. Hay situaciones en las que el padre de un elemento absolutamente posicionado está en sí mismo absolutamente posicionado. Esto es completamente normal. Si todos los padres son estáticos, se adjuntará un elemento en posición absoluta a la ventana gráfica, pero de modo que se desplace junto con la ventana gráfica.


Hay una adición poco conocida a las reglas mencionadas anteriormente: en situaciones en las que el elemento padre tiene la propiedad de transform ( entre otros ) con un valor distinto de none , se convierte en un bloque contenedor para elementos posicionados de manera absoluta y fija. La confirmación de esto se puede ver en CodePen, donde el elemento con el texto "¡Aviso!" Es un elemento fijo, y el padre tiene la propiedad de transformación, pero solo cuando el cursor del mouse está sobre él (en estado :hover )


Pregunta 4: margen de colapso de elementos primarios y secundarios


Esta es una de esas pequeñas cosas de CSS que pueden causar muchos problemas si no sabes cómo funciona. Existe un concepto llamado márgenes de colapso y muchas personas están familiarizadas con la manifestación de esto, llamados márgenes de colapso de los hermanos adyacentes. Sin embargo, hay otra forma, llamada los márgenes de colapso del padre y el primer / último hijo, que es menos conocida. La siguiente es una demostración de ambos casos:


Cada etiqueta de párrafo tiene un margen superior e inferior igual a 1em, que está diseñado por el navegador. Hasta ahora, esta es la parte más fácil de la situación. Pero, ¿por qué el espacio entre párrafos no es 2em (la suma de la parte superior e inferior)? Esto se llama márgenes de colapso de los hermanos adyacentes. Los márgenes se superponen de tal manera que el mayor de los dos márgenes será el tamaño del espacio, por lo que en este caso el espacio será 1em.

Sin embargo, algo más extraño está sucediendo. ¿Notó que el margen superior del primer párrafo no crea un espacio entre este y el contenedor azul div? En lugar de romperse, parece incrustar un margen en el div principal, como si el div tuviera un margen superior. Esto se llama márgenes de colapso del padre y el primer / último hijo. Este tipo de márgenes de colapso no ocurrirá bajo ciertas circunstancias si lo siguiente es característico del padre:

  • Hay un relleno superior / inferior mayor que cero
  • Hay un borde superior / inferior mayor que cero
  • Se especifica un contexto de formato de bloque que se puede crear usando overflow: hidden o overflow: auto
  • Pantalla: conjunto de propiedades de la raíz del flujo (soporte deficiente del navegador)

Cuando me complace explicar a la gente este pequeño detalle CSS y resolverlo con relleno o borde, la respuesta casi siempre es: "¿Qué pasa con el relleno o borde igual a 0?". Bueno, esto no funciona, porque el valor debe ser un número entero positivo.

En el ejemplo anterior, el relleno de 1px nos permite cambiar entre usar el colapso y evitar los márgenes de colapso del padre y el hijo. El espacio que aparece entre el primer / último párrafo y el padre es un relleno de 1px, pero ahora el margen se considera el interior del contenedor, porque la capa de relleno crea una barrera para evitar que los márgenes se contraigan.

En cuanto a la pregunta, estoy seguro de que puedes ver cuál es el problema en esta interfaz:


El primer elemento con la clase .comment (sin la clase .moderator ) contrae los márgenes. Incluso sin mirar el código, podemos ver que el elemento con la clase .moderator tiene un marco, y el elemento sin esta clase no. En realidad, hubo tres respuestas a esta pregunta que se consideraron correctas. De hecho, cada una de ellas ya está aplicada en la fuente de CodePen, solo se comentan.

Una de las razones por las que este tipo de márgenes de colapso no es tan conocido como los otros es porque hay muchas situaciones en las que podemos evitarlo accidentalmente. Los elementos Flexbox y Grid crean un contexto de formato de bloque, por lo que al usarlos no encontramos este tipo de márgenes de colapso. Si la interfaz de nuestros comentarios fue un proyecto real, es muy probable que se hayan colocado almohadillas en los cuatro lados para dejar espacio, y esto, a su vez, solucionó el colapso de los márgenes para nosotros.

Pregunta 5: ¿Porcentaje de qué?


Cuando se utilizan unidades de porcentaje, los porcentajes se basan en el ancho o alto del bloque contenedor (generalmente el padre). Como dijimos anteriormente, un elemento con la propiedad de transform se convertirá en un bloque contenedor, por lo que cuando el elemento usa transformación, las unidades en porcentaje (solo para la transform ) se en el tamaño del elemento y no en el tamaño principal.

En el siguiente ejemplo, podemos ver que el 50% adquiere dos valores diferentes según el contexto. El primer bloque rojo tiene la propiedad margin-left: 50% , y el segundo bloque rojo usa transform: translateX(50%) .


Pregunta 6: El modelo de bloque ataca de nuevo ...


Solo que pensaste que habíamos terminado de hablar sobre el modelo de bloques ...


El problema se debe al hecho de que usamos width: 100% para el pie de página y al mismo tiempo agregamos relleno. El ancho del contenedor es de 500px, lo que significa que la capa de contenido del pie de página (que es 100%) también es de 500px antes de que se agreguen rellenos a este tamaño.

El problema se puede solucionar mediante una de dos técnicas comunes:

  1. Use la propiedad de tamaño de cuadro para el pie de página directamente o mediante el restablecimiento mencionado anteriormente
  2. Elimine la propiedad de width del elemento y use las propiedades left: 0 y right: 0 en su lugar. Este es un buen ejemplo del uso de las propiedades left y right al mismo tiempo. Este enfoque evita los problemas del modelo de bloque, porque la propiedad de width usará su valor predeterminado auto para llenar cualquier espacio disponible entre el relleno y los bordes cuando se establecen left: 0 y right:0 .

Nota: Una opción era eliminar el relleno del pie de página. Técnicamente, esto solucionaría el problema, porque la capa de contenido sería 100% y no tendría relleno o borde para expandirse más allá del ancho del contenedor. Pero creo que esta solución es el enfoque incorrecto, porque no tenemos que cambiar nuestra interfaz para adaptarnos a los problemas del modelo de bloque, que se solucionan fácilmente sin él.

La realidad para mí es que siempre tengo la propiedad box-sizing: border-box como parte de mi reinicio de estilo general. Si hace lo mismo, lo más probable es que rara vez encuentre este problema. Pero todavía me gusta la técnica de establecer las propiedades left:0 y right:0 al mismo tiempo, porque, como muestra el tiempo, es más confiable (en cualquier caso, a juzgar por mi experiencia) que resolver los problemas del modelo de bloques que surgen debido al ancho 100%

Pregunta 7: Centrar elementos absolutos y fijos


Ahora estamos realmente comenzando a combinar todo el material descrito anteriormente, con el centrado de los elementos absolutos y fijos:


Como ya hemos cubierto la mayor parte del material en esta pregunta de prueba, simplemente indico que el centrado horizontal y vertical se puede hacer usando el método de la vieja escuela a través de márgenes negativos, o más nuevo usando la propiedad de transformación. También traigo a su atención una excelente guía de centrado de elementos CSS-Tricks .

Nota : hace algún tiempo se argumentó que si conocemos el ancho y la altura del bloque, deberíamos usar márgenes negativos, porque funcionan de manera más estable que la nueva propiedad de transformación. Por el momento, la transformación funciona de manera estable y casi siempre uso esta propiedad, a menos que necesite evitar convertir el bloque al que lo contiene.

Pregunta 8: Centrar elementos en un flujo normal


Flexbox nos trajo muchas herramientas increíbles para resolver problemas complejos de diseño. Antes de su lanzamiento, se informó que el centrado vertical era una de las características más complejas que se implementaron en CSS. Con la llegada de Flexbox, el centrado vertical se ha convertido en rutina:

 .parent { display: flex; } .child { margin: auto; } 

https://codepen.io/bradwestfall/pen/GPNmbM
Nota : tenga en cuenta que para los elementos flexibles, el margen: automático se aplica en los lados superior, inferior, derecho e izquierdo para centrar el elemento vertical y horizontalmente. Anteriormente, el centrado vertical no funcionaba para elementos de bloque, por lo que el margin: 0 auto; bastante común margin: 0 auto;

Pregunta 9: Cálculos con diferentes unidades.


El uso de la función calc () es excelente cuando necesita trabajar con dos unidades de medida que no podemos sumar por nuestra cuenta o cuando necesitamos que las fracciones sean más fáciles de entender . Esta pregunta de prueba nos ofrece descubrir cómo será el resultado de la expresión calc(100% + 1em) , comenzando por el hecho de que el ancho del elemento div es 100px. Esto podría ser un poco confuso, porque de hecho, no importa que el ancho del elemento div sea de 100 px. Los porcentajes siempre comienzan desde el ancho del padre, por lo que la respuesta correcta fue: "100% del bloque que contiene (padre) más 1em".

Hay varias situaciones en las que uso regularmente calc() . En primer lugar, cada vez que quiero cambiar algo en un 100%, pero también agregar una cantidad fija de espacio extra. Los menús desplegables pueden ser un buen ejemplo de esto:


La peculiaridad aquí es que queremos crear un menú desplegable que pueda usarse junto con los elementos de llamada de diferentes tamaños (en este caso, dos tamaños diferentes de botones). No sabemos cuál será la altura del elemento que llama a este menú, pero sabemos que top: 100% colocará el borde superior del menú desplegable en el borde inferior del botón de llamada. Si cada menú debe estar en el borde inferior del botón correspondiente, más 0.5em, esto se puede lograr con calc(100% + 0.5em) . Por supuesto, también podríamos usar top: 110% , pero este 10% adicional dependería de la altura del botón de llamada y el contenedor.

Pregunta 10: márgenes negativos


A diferencia de los márgenes positivos que repelen a los hermanos, los márgenes negativos los acercan entre sí sin desplazarlos . Esta pregunta final de la prueba ofrece dos soluciones, que técnicamente eliminan el doble borde en nuestro grupo de botones, pero prefiero la técnica de margen negativo, porque eliminar los marcos dificultaría la realización de ciertas técnicas, como el efecto mouseover.


El efecto resultante es un "borde común" que se muestra entre los botones. De hecho, los botones no pueden tener un borde común, por lo que debemos usar una técnica de margen negativo para que un cuadro se superponga con otro. Luego uso z-index para establecer qué marco quiero ajustar por encima de otro, según el estado del mouse. Tenga en cuenta que z-index es útil aquí incluso sin utilizar el posicionamiento absoluto, pero tenía que establecer la position: relative . Si utilizara la técnica de eliminar el marco izquierdo del segundo botón, este efecto sería mucho más difícil de implementar.

Todo tiene sentido.


Quiero mostrarles otra demostración más reciente que utiliza muchos de los trucos que discutimos antes. La tarea es crear mosaicos que se expandan a los bordes izquierdo y derecho del contenedor, teniendo en cuenta la sangría. Por azulejos, me refiero a la capacidad de tener una lista de bloques que se ajustan a la siguiente línea cuando no hay suficiente espacio de ancho. Desplácese sobre los mosaicos para ver el resultado:


Un obstáculo para realizar esta tarea es la sangría. Sin relleno, sería fácil obtener mosaicos adyacentes a los bordes izquierdo y derecho del contenedor. El problema es que las sangrías se crearán usando márgenes, y cuando agregamos márgenes en todos los lados del mosaico, creamos dos problemas:

  1. La presencia de tres mosaicos con un ancho de 33.33% junto con el margen no podrá caber en una fila. Aunque box-sizing nos permite tener relleno y bordes en el elemento .tile y encajar en 33.33% , esto no nos ayudará en el caso de los márgenes, lo que significa que el ancho calculado de las tres fichas será más del 100%, lo que obligará a la última ficha a pasar al siguiente cuerda
  2. Las fichas izquierda y derecha ya no se colocarán contra el borde del contenedor.

El primer problema se puede resolver con calc((100% / 3) - 1em). Lo que significa 33.33% menos los márgenes izquierdo y derecho de cada mosaico. El colapso de los elementos hermanos adyacentes no ocurrirá aquí, ya que solo es posible en el margen superior e inferior. Como resultado, la distancia horizontal entre dos mosaicos es la suma de dos márgenes (1em). En este caso, el colapso tampoco se aplica a los márgenes superior e inferior, porque el primer y el último mosaico no son técnicamente adyacentes, incluso si visualmente uno está debajo del otro.

Al tomar concalc()Pueden encajar tres fichas en una fila, pero aún así no tocan los bordes del contenedor. Para hacer esto, podemos usar márgenes negativos en el tamaño igual a los márgenes izquierdo y derecho de cada mosaico. La línea punteada verde en el ejemplo es un contenedor donde aplicamos márgenes negativos para dibujar mosaicos correspondientes al borde del contenido circundante. Podemos ver cómo se ajustan al área de relleno del elemento padre. Esto es normal porque los márgenes negativos no repelen los elementos vecinos circundantes.

Como resultado, obtenemos mosaicos que tienen espacios suficientes que se expanden de borde a borde para que se alineen con las etiquetas de párrafo adyacentes fuera de los mosaicos.

Hay muchas formas de hacer mosaicos (y generalmente tienen sus ventajas y desventajas). Por ejemplo, hay una solución CSS Grid bastante elegante de la que habló Haydon Pickering. Esta solución se implementa utilizando una técnica que simula las solicitudes de contenedores (pero utilizando la magia Grid). En última instancia, su solución usando Grid es mejor que flexbox, que demostré pero tiene peor soporte para el navegador.

Resumen


Al principio, dije que me inclinaba a buscar patrones para resolver problemas. Este artículo no trata tanto sobre los escenarios demostrados anteriormente; se trata más de un conjunto de herramientas que se pueden usar para resolver estos y muchos otros problemas de composición tipográfica que todos podemos enfrentar. Espero que estas herramientas te ayuden.

Por cierto, hay una serie de excelentes recursos que examinan cuidadosamente el tema del modelo de bloques. En primer lugar, artículos de Rachel Andrew y Jen Simmons, que definitivamente vale la pena leer.

  • Cheatsheet Box Alignment es un excelente material con elementos visuales que enfatizan varias propiedades que afectan la forma en que los elementos se alinean por sí mismos o en relación con otros elementos.
  • Jen Simmons Labs — , .

Source: https://habr.com/ru/post/467555/


All Articles