====== 3. CSS: Flex y Grid ====== En este tema vamos a explicar el layout en CSS con //flexbox// y //grid//. ===== Flexbox ===== Flex se utiliza para colocar cosas de forma horizontal o vertical. * [[https://css-tricks.com/snippets/css/a-guide-to-flexbox/|A Complete Guide to Flexbox]] * {{:clase:daw:diw:css_flexbox_layout_cheatsheet.pdf|Flexbox Layout Cheatsheet. Otra guía rápida de flexbox}} * [[https://medium.com/@js_tut/the-complete-css-flex-box-tutorial-d17971950bdc|The Complete CSS Flex Box Tutorial]] * [[https://medium.com/@js_tut/flexbox-the-animated-tutorial-8075cbe4c1b2|Flexbox — The Animated Tutorial]] * [[https://stackoverflow.com/questions/32551291/in-css-flexbox-why-are-there-no-justify-items-and-justify-self-properties|In CSS Flexbox, why are there no “justify-items” and “justify-self” properties?]] * [[https://flexboxfroggy.com/#es|Flexbox Froggy - A game for learning CSS flexbox]]. Vamos a explicar flex con el siguiente ejemplo:
Item1
Item2
Item3
Item4
Item5
.contenedor { display: flex; flex-direction: row; } .item-grande { flex-grow: 2; } Como vemos hay dos tipos de elementos, el contenedor y los items que hay dentro. El contenedor siempre tendrá la siguiente línea ''display:flex;''. * Un item puede ser a su vez un contenedor flex:
Item1.1
Item1.2
Item2
Item3
Ahora veremos algunas de las opciones que permite flex. ==== flex-direction ==== Para hacer que los item se muestren de forma vertical u horizontal. Sus valores son * ''flex-direction:row'' Los items se colocan en horizontal. Es decir en una única línea. {{:clase:daw:diw:flex-row.png|}} * ''flex-direction:column'' Los items se colocan en vertical. Es decir en una única columna. {{:clase:daw:diw:flex-colum.png|}} ==== flex-wrap ==== Para hacer que si no caben en una línea, se pasen a la línea siguiente. * ''flex-wrap:wrap'' Si se añade se pasa de línea en vez de mantenerse en la misma {{:clase:daw:diw:flex-wrap.png|}} ==== justify-content ==== Es como se distribuye el espacio sobrante en horizontal. Hacía la izquierda, derecha, ocupando todo el espacio, etc, etc. Alguno de sus posibles valores son: * ''justify-content:flex-start'' * ''justify-content:flex-end'' * ''justify-content:center'' * ''justify-content:space-between'' * ''justify-content:space-around'' * ''justify-content:space-evenly'' {{:clase:daw:diw:flex-justify-content.png|}} ==== align-content ==== Es como se distribuye el espacio sobrante en vertical. Hacía arriba, abajo, ocupando todo el espacio, etc, etc. Alguno de sus posibles valores son: * ''align-content:flex-start'' * ''align-content:flex-end'' * ''align-content:center'' * ''align-content:stretch'' * ''align-content:space-between'' * ''align-content:space-around'' {{:clase:daw:diw:flex-align-content.png|}} ==== align-items ==== Si los elementos se justifican hacía arriba, abajo, ocupando todo el espacio, etc, etc. Alguno de sus posibles valores son: * ''align-items:flex-start'' * ''align-items:flex-end'' * ''align-items:center'' * ''align-items:stretch'' * ''align-items:baseline'' {{:clase:daw:diw:flex-align-items.png|}} ==== flex-grow ==== Permite que crezca el item si hay mas espacio. Por defecto el valor es ''0'' que significa que no crece, sino que se queda con el espacio que necesita para su contenido. * ''flex-grow:1'': Todos los items con este valor crecerán para ocupar más espacio pero todos los que tengan este valor tendrán el mismo tamaño entre ellos * ''flex-grow:2'': Como al anterior pero todos los que tengan este valor tendrán el mismo tamaño entre ellos pero el **doble** que los de ''flex-grow:1'' * ''flex-grow:3'': Como al anterior pero todos los que tengan este valor tendrán el mismo tamaño entre ellos pero el **triple** que los de ''flex-grow:1'' {{:clase:daw:diw:flex-grow.png|}} Se usa dentro de los "hijos" En el siguiente ejemplo, ''AAAAA'' tendrá el espacio mínimo para que quepa el texto mientras que ''BBBBB'' y ''CCCCC'' se expandirán hasta ocupar todo el espacio disponible pero ''CCCCC'' ocupará el doble que ''BBBBB''
AAAAA
BBBBB
CCCCC
Si definimos ''flex-grow'', el item crecerá hasta tener un tamaño mayor o justo el del contenido, así que no tiene sentido usar ''flex-shrink:1'' ya que ya se podría hacer más pequeño ni usar ''flex-basis'' ya que no tendrá un tamaño fijo. ==== flex-shrink ==== Indica que un item puede reducir su tamaño en comparación con otros items cuando el contenedor es más pequeño que el tamaño total de los elementos. * ''flex-shrink:1'': Los items con este valor pueden reducir su tamaño para ajustarse al contenedor. * ''flex-shrink:0'': Los items con este valor no se reducirá, independientemente del tamaño del contenedor. Ejemplo: Si tienes tres elementos en un contenedor y uno tiene flex-shrink: 0, este no se reducirá, mientras que los otros dos se reducirán según sea necesario para encajar en el contenedor. Se usa dentro de los "hijos" Solo tiene sentido usar ''flex-shrink:1'' si se indica ''flex-basis'' y su valor no es ''auto''. Ya que si ''flex-basis:auto'' el item ya tendrá el tamaño mínimo del contenido así que no se podrá hacer más pequeño y por lo tanto no se necesita ''flex-shrink:1'' ==== flex-basis ==== Define el tamaño inicial de un item antes de que se aplique el crecimiento o la reducción. Es el tamaño en el que se basa el elemento antes de que el espacio adicional sea distribuido (con ''flex-grow'') o el espacio sea reducido (con ''flex-shrink''). El tamaño inicial se puede establecer en ''px'', ''%'', ''em'', etc. Por defecto el tamaño inicial es ''auto'' y significa que el tamaño es el del contenido. Se usa dentro de los "hijos" Veamos ahora un ejemplo completo de las 3 propiedades: Ejemplo de Flexbox
AAAAAAAAAAAAAAA
BBBBBBBBBBBBBBB
CCCCCCCCCCCCCCC
La explicación es: * El ''item1'' empieza con un tamaño de ''300px'' (por ''flex-basis: 300px;'') pero se puede hacer más pequeño si es necesario (por ''flex-shrink: 1;'') * El ''item2'' empieza con un tamaño de ''300px'' (por ''flex-basis: 300px;'') pero **NO** se puede hacer más pequeño (por ''flex-shrink: 0;'') * El ''item3'' ocupará todo el espacio que haya libre (por ''flex-grow:1'') y eso incluye hacerlo más grande o pequeño ==== flex ==== Es poner en una misma linea ''flex-grow'', ''flex-shrink'' y ''flex-basis'' Se usa dentro de los "hijos" Mas información en: * [[https://css-tricks.com/understanding-flex-grow-flex-shrink-and-flex-basis/|Understanding flex-grow, flex-shrink, and flex-basis]] * [[https://www.paradigmadigital.com/dev/diferencia-flex-basis-width/|Diferencia entre flex basis y width]] * [[https://ed.team/blog/guia-definitiva-de-flexbox-2-flex-basis-flex-frow-flex-shrink|Guia definitiva de Flexbox (2): Flex basis, flex-frow, flex-shrink]] * [[https://www.desarrollolibre.net/blog/css/las-propiedades-flex-grow-flex-shrink-y-flex-basis|Las propiedades flex-grow, flex-shrink y flex-basis]] ==== margin y auto ==== Una utilidad de flexbox es hacer menús pero a veces queremos mover algunos item hacia la derecha. El truco para hacerlo es usar ''margin-left: auto;'' En las siguientes páginas se indica cómo hacerlos.
Item1
Item2
Item3
Item4
Item5
En el ejemplo, los items 1 , 2 y 3 estarán pegados a la izquierda y los items 4 y 5 estarán pegados a la derecha. Mas información en: * [[https://medium.com/flexbox-and-grids/the-most-popular-navigation-bars-created-with-flexbox-6c0f59f55686|The Most Popular Navigation Bars created with Flexbox]] * [[https://github.com/ohansemmanuel/Understanding-Flexbox/blob/master/05.%20Auto%20margin%20alignment/auto_margin.md|Understanding Flexbox - auto-margin]] {{ :clase:daw:diw:flex-frog.png?direct&100 |}} Para aprender flexbox puede jugar a [[https://flexboxfroggy.com/#es|Flexbox Froggy - A game for learning CSS flexbox]] ===== Grid ===== Grid permite colocar cosas en dos dimensiones. Como si fuera una rejilla (un grid en inglés). * Guías completas de Grid: * [[https://css-tricks.com/getting-started-css-grid/|Getting Started with CSS Grid]] * [[https://css-tricks.com/snippets/css/complete-guide-grid|A Complete Guide to Grid]] * [[https://tympanus.net/codrops/css_reference/grid/|CSS Grid is a two-dimensional layout system created specifically to tackle grid-based user interfaces on the web.]] * [[https://www.codeinwp.com/blog/css-grid-tutorial-layout/|The Ultimate CSS Grid Tutorial for Beginners (With Interactive Examples)]] * {{:clase:daw:diw:css_grid_layout_cheatsheet.pdf|}} * Grid vs FlexBox: * [[https://www.youtube.com/watch?v=hs3piaN4b5I|Video:Flexbox vs. CSS Grid — Which is Better?]] * [[https://css-tricks.com/css-grid-replace-flexbox/|Does CSS Grid Replace Flexbox?]] * Mas información: * [[https://css-tricks.com/almanac/properties/j/justify-items/|justify-items]] * [[https://www.youtube.com/watch?v=0Gr1XSyxZy0|Los 9 grandes errores con CSS Grid]] * [[https://css-tricks.com/things-ive-learned-css-grid-layout/|Things I’ve Learned About CSS Grid Layout]] * [[https://www.webstoemp.com/blog/notes-on-using-css-grid-in-production/|Notes on using CSS Grid in production]]: Cómo se usa grid en un proyecto real * [[https://gridbyexample.com/|Grid by Example]] .contenedor { display:grid; grid-template-columns: 1fr 1fr 2fr; grid-template-rows: 1fr 2fr; } .item { border:1px solid red; }
Item1
Item2
Item3
Item4
Item5
Item6
==== grid-template-columns ==== Indica el tamaño de cada columna Las unidades pueden ser: * Tamaño fijo: Usar px * auto: Coge el menor tamaño posible * fr: Es una fracción del espacio libre después de quitar las columnas de tamaño fijo (Las 2 formas anteriores, px y auto) Ejemplos: * ''grid-template-columns: 1fr 1fr 2fr'' La última columna tendrá el doble de tamaño que las anteriores * ''grid-template-columns: 1fr 1fr 50px'' La segunda columna tendrá el mismo de tamaño que la primera. La última siempre 50px * ''grid-template-columns: 1fr 2fr 80px auto'' La última tendrá un tamaño mínimo posible, la tercera tendrá 80px, la segunda el doble que la primera. ==== repeat ==== Si hay muchas columnas y todas del mismo tamaño en vez de .contenedor { grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; } se puede escribir: grid-template-columns: repeat(6, 1fr); \\ \\ o en vez de .contenedor { grid-template-columns: 100px 100px 100px 100px 100px 100px ; } se puede escribir: grid-template-columns: repeat(6, 100px ); ==== auto-fit ==== Si el tamaño de las columnas es fijo se puede hacer lo siguiente para no especificar el número de columnas y que sea variable según el ancho de la ventana: .contenedor { grid-template-columns: repeat(auto-fit, 100px ); } En ese caso ocupará todas las filas que sea necesario para poder poner ponerlo todo. Es una forma de hacer las cosas responsivas. \\ \\ Por último se puede usar la función ''minmax'' de CSS para hacerlo de la siguiente forma .contenedor { grid-template-columns: repeat( auto-fit, minmax( 100px, 1fr ) ); } Que hará que cada columna ocupe como mínimo 100px y si hay mas espacio crecerá hasta ocupar todo. Pero se crearán tantas filas como sea necesario. Mas información en [[https://timwright.org/blog/2017/08/26/css-grid-layout/|repeat,auto-fit,minmax,1fr]] y en [[https://www.youtube.com/watch?v=mVQiNpqXov8|MinMax in CSS Grid — 3/3 Flexibility]] La función ''minmax'' es similar a las propiedades css de: * ''min-width'' * ''min-height'' * ''max-width'' * ''max-height'' ==== Ejemplo ==== Veamos ahora un ejemplo de la diferencia entre ''repeat(4,1fr)'' , ''repeat(auto-fit,100px)'' y ''repeat( auto-fit, minmax( 100px, 1fr ) )'' .contenedor { display:grid; grid-template-columns: repeat(4,1fr); } .contenedor2 { display:grid; grid-template-columns: repeat(auto-fit,100px); } .contenedor3 { display:grid; grid-template-columns: repeat( auto-fit, minmax( 100px, 1fr ) ); } .contenedor4 { display:grid; grid-template-columns: repeat( 4, minmax( 100px, 1fr ) ); } .item { border:1px solid red; } .item2 { border:1px solid green; } .item3 { border:1px solid blue; } .item4 { border:1px solid pink; }

repeat(4,1fr)

Item1
Item2
Item3
Item4
Item5
Item6
Item7
Item8

repeat(auto-fit,100px)

Item1
Item2
Item3
Item4
Item5
Item6
Item7
Item8

repeat( auto-fit, minmax( 100px, 1fr ) )

Item1
Item2
Item3
Item4
Item5
Item6
Item7
Item8

repeat( 4, minmax( 100px, 1fr ) )

Item1
Item2
Item3
Item4
Item5
Item6
Item7
Item8
==== grid-template-rows ==== Es lo mismo que ''grid-template-columns'' pero referido a las filas. ==== gap ==== Indica la separación entre cada una de las celdas del grid. .contenedor { gap: 15px 10px; } {{:clase:daw:diw:grid-gap.png|}} La propiedad ''gap'' también funciona con **flex** ==== span ==== Se puede hacer que un elemento ocupe más de una columna con ''grid-column: span x;'' siendo ''x'' el número de columnas que quieres que se expanda. .contenedor { display: grid; grid-template-columns: repeat(4, 1fr); } .doble { grid-column: span 2; }
Item1
Item2
Item3
Item4
Item5
Item6
Item7
* Mas información * [[https://webdesign.tutsplus.com/how-to-build-web-form-layouts-with-css-grid--cms-28776t|How to Build Web Form Layouts With CSS Grid]] * [[https://www.scale.at/blog/responsive-form-layout-css-grid|Tutorial: A Responsive Form Layout with CSS Grid]] ==== grid-template-areas ==== la propiedad ''grid-template-areas'' permite especificar exactamente como colocar los div en un contenedor. Para explicarlo lo vamos a ver con un ejemplo. TODO supply a title
CABECERA
IZQUIERDA
CUERPO
DERECHA
PIE
Mas información: * [[https://css-tricks.com/almanac/properties/g/grid-template-areas/|grid-template-areas]] * [[https://www.smashingmagazine.com/understanding-css-grid-template-areas/|Understanding CSS Grid: Grid Template Areas]] Artículos en general sobre Layout: * [[http://1linelayouts.glitch.me/|1-Line Layouts.10 Modern CSS layout and sizing techniques]] * [[https://moderncss.dev/|Modern CSS Solutions]] ===== Ejercicios ===== ==== Ejercicio 1 ==== Haz una página HTML con cabecera, lateral izquierdo, cuerpo, lateral derecho y pie usando ''grid-template-areas''. Dentro de la cabecera pon un menú hecho con flex en el que los dos últimos elementos estén pegados a la derecha. ==== Ejercicio 2 ==== Crea la siguiente página web [[https://nemo.wickedtemplates.com/|Wicked Templates || Nemo]]. Si la página no está accesible tienes una copia aqui: {{ :clase:daw:diw:wicked_teplates_nemo.zip |}} Si quieres variar el fondo, puedes obtener imágenes de [[https://pngtree.com/free-backgrounds-photos/|Background Photos, Vectors and PSD Files for Free Download | Pngtree]]