Tutorial para anular funciones del tema padre con un tema hijo

Tutorial para anular funciones del tema padre con un tema hijo

Si eres desarrollador web quizá en algún momento de tu carrera te ha tocado trabajar con WordPress y muy probablemente con un tema comprado por ti o por un cliente. O en el mejor de los casos tu mismo estás desarrollando un tema.

Hay ocasiones en las que necesitas modificar alguna funcionalidad del theme cómo, por ejemplo cuándo quieras cambiar el layout de alguno de los archivos de plantillas.

En este caso lo que se hace es copiar los archivos del tema original que vas a modificar y pegarlos en el tema secundario. Haciendo esto, automáticamente WordPress anula el archivo en el tema principal.

Desafortunadamente las funciones no trabajan igual. Para lograr que trabajen es necesario sobrescribir las funciones del tema padre, mediante el archivo functions.php del tema hijo o child theme.

En este tutorial, te mostraré tres maneras que puedes usar para anular funciones del tema padre con un tema hijo:

  • Funciones pluggables o conectables
  • Prioridad de la función
  • Quitar funciones del gancho al que están sujetos

Sobrescribir archivos de la plantilla es fácil, digamos que en el tema padre tienes un archivo que se llama single.php, si este mismo archivo lo creas en tu tema hijo, WordPress automáticamente va a utilizar el archivo del tema hijo, anulando así el archivo de plantilla del tema padre.

Desafortunadamente no sucede lo mismo con las funciones dentro del archivo functions.php. El proceso es un poco más elaborado, como lo veremos más adelante.

Cómo trabajan las funciones dentro del archivo functions.php

Para entender cómo es que las funciones del hijo sobrescriben a las del parent theme, tenemos que saber cómo es que trabajan las funciones en WordPress.

Cuando usas un tema hijo, automáticamente WordPress se encarga de ejecutar las funciones del tema padre. Esto no sucede con los estilos CSS, que tienes que importar el archivo style.css que contiene los estilos del tema padre.

Te voy a platicar de un punto importante que te evitará dolores de cabeza. Si tienes funciones con el mismo nombre en el padre y en el hijo… Prepárate para el desastre; tu sitio se va a romper. Para evitar que esto ocurra procura usar prefijos para nombrar tus funciones en el tema hijo y de ser posible en el tema principal.

1. Funciones pluggables o conectables

Este tipo de funciones trabajan en el tema principal y solo sí el desarrollador las implementa, así que si tu tema no las usa de nada te va a servir.

Para escribir una función pluggable, tienes que encerrarla en una etiqueta condicional para comprobar si una función con ese nombre ya ha sido ejecutada:

<?php
if ( ! function_exists ( 'prefix_my_function' ) ) {
    function prefix_my_function() {
        // Cuerpo de la función.
    }f
}
?>

La función function_exists() va a revisar si ya se ha definido una función con el nombre prefix_my_function en el tema hijo, si es así la función del tema principal no se ejecutará.

Cuando quieras anular una función del tema padre, escribe una función en el tema hijo con el mismo nombre de la función del tema padre.

<?php
  function prefix_my_function() {
      // Contenido de la función que sobrescribe la función padre
  }
?>

El núcleo de WordPress ejecutará en primer lugar la función del tema hijo, cuando le toque al padre ejecutar la condición, WordPress comprobará si ya existe una función con el mismo nombre y si es así no la ejecutará.

Este tipo de funciones son de gran utilidad y muy fáciles de usar, ya se pueden anular sin mucho esfuerzo.

2. Modificar la prioridad de la función

Si la plantilla de terceros que compraste no implementa las funciones conectables o no las estás implementando en el tema que estás desarrollando, en ese caso deberías de empezar a usarlas en los temas que desarrolles. De no ser posible eso, cambiar la prioridad de las funciones es lo que necesitas.

Cuando agregas funciones a WordPress lo haces con las funciones add_action() y add_filter(), estas funciones reciben un parámetro opcional de prioridad que se utiliza para especificar el orden en el que se ejecutan las funciones asociadas con una acción en particular.

Tiene un orden ascendente, esto es de menor a mayor y por defecto la prioridad tiene un valor de 10. Yo te recomiendo incrementar el valor en más cinco (15, 20, 25, 30, etc.). Al hacerlo de esta manera vas a tener un poco de espacio en caso de que quieras añadir otra función entre las dos más tarde.

<?php
  function prefix_child_function() {
      // Cuerpo de la función.
  }
  add_action( 'init', 'prefix_child_function', 15 );
?>

En el tema padre, te vas a encontrar con funciones que tienen definida la propiedad de prioridad, y se ven así:

<?php
  function prefix_parent_function() {
      // Cuerpo de la función.
  }
  add_action( 'init', 'prefix_parent_function', 20 );
?>

Así que solo tienes que asegurarte de que la prioridad que le das a la función en el tema hijo es mayor:

<?php
  function prefix_child_function() {
      // Cuerpo de la función.
  }
  add_action( 'init', 'prefix_child_function', 25 );
?>

Eliminando funciones de los ganchos

Para eliminar una función del tema padre hay que removerlas del gancho al que están conectados. Eso se logra con las funciones remove_action() o remove_filter(). El que utilices dependerá de si la función está conectada a un gancho de acción o a un gancho filtro en el theme principal.

Volvamos a nuestra función anterior en el tema padre:

<?php
  function prefix_parent_function() {
      // Cuerpo de la función.
  }
  add_action( 'init', 'prefix_parent_function', 20 );
?>

Para eliminar esta función de tu gancho de acción y, por lo tanto, evitar que se dispare, crea una función en el tema hijo para eliminarla usando remove_action():

<?php
	remove_action( 'init', 'prefix_parent_function' );
?>

remove_action() por si sola no va a funcionar, es necesario conectar esta función a un gancho que se dispare después del gancho al que está conectada la función del tema principal. Esto se debe a que no puedes quitar una acción antes de que haya sido ejecutada. Puedes encontrar detalles del orden en que se disparan las acciones en la documentación de WordPress.

<?php
  function prefix_child_remove_parent_function() {
      remove_action( 'init', 'prefix_parent_function' );
  }
  add_action( 'wp_loaded', 'prefix_child_remove_parent_function' );
?>

Nota importante sobre la prioridad

Ten en cuenta que si la función del tema padre tiene una prioridad asignada diferente al número 10, debes incluirla en la función remove_action() o remove_filter(), de lo contrario no va a funcionar.

Tenemos la función en el tema padre:

<?php
  function prefix_parent_function() {
      // Cuerpo de la función.
  }
  add_action( 'init', 'prefix_parent_function', 20 );
?>

Para poder eliminarla vamos a tener que establecer el mismo valor de prioridad:

<?php
  function prefix_child_remove_parent_function() {
      remove_action( 'init', 'prefix_parent_function', 20 );
  }
  add_action( 'wp_loaded', 'prefix_child_remove_parent_function' );
?>

Recomendaciones

Para crear una nueva función, puedes copiar y pegar la función del tema padre en el archivo functions.php del tema hijo, y luego editarlo para eliminar el código que no necesites.

Vas a crear dos funciones: una para eliminar la original, y la segunda para proporcionar la nueva funcionalidad. En el siguiente ejemplo anulamos la función prefix_parent_theme_function y colocamos la nueva función prefix_child_theme_function en el gancho ‘init’:

<?php
  function prefix_remove_parent_theme_function() {
      remove_action( 'init', 'prefix_parent_theme_function');
  }
  add_action( 'wp_loaded', 'prefix_remove_parent_theme_function');

  function prefix_child_theme_function() {
      // contenido de la función del tema hijo basado en la función del tema principal
  }
  add_action( 'init', 'prefix_child_theme_function');
?>

Si estás desarrollando un tema, es una buena práctica hacer que tus funciones sean conectables para que pueda anularlas fácilmente en el tema hijo.

También es una buena idea revisar las funciones que se escriben en el tema padre que estás usando, y así identificar de que manera vas a trabajar. Revisa si tiene funciones pluggables:

<?php
if ( ! function_exists ( 'prefix_my_function' ) ) {
    function prefix_my_function() {
        // Cuerpo de la función.
    }f
}
?>

Resumen

Anular funciones del tema padre con un tema hijo es más complicado que anular los archivos de plantilla o los estilos. Aquí te he mostrado tres maneras para hacerlo:

  • Funciones pluggables o conectables: estás funciones sirven si el tema de terceros o el tema que estas desarrollando las implementa, recuerda nombrar las funciones en el tema hijo con el mismo nombre que tiene la función en el parent theme para que pueda ser sustituida.
  • Modificar la prioridad de la función: Asigna prioridades más altas a las funciones del tema hijo para asegurarte de que se ejecuten después de las del tema padre.
  • Remover funciones de los ganchos: Utiliza remove_action() o remove_filter() para eliminar completamente las funciones del tema principal.

El método que vayas a utilizar va a depender de cómo este desarrollado tu theme, lo más seguro es que tengas que utilizar las tres formas para anular funciones del tema padre con un tema hijo, al trabajar en el aspecto y funcionamiento de las plantillas del tema.

 

Cómo ocultar precios a usuarios no registrados o sin sesión en Woocommerce

Cómo ocultar precios a usuarios no registrados o sin sesión en Woocommerce

Al trabajar con Woocommerce y al ser una tienda virtual que se integra con facilidad a WordPress, su uso puede resultar familiar para muchos usuarios, en este caso clientes que tienen productos físicos o virtuales y los quieren vender en linea.

Existen negocios que quieren ocultar precios a usuarios que no tienen una cuenta con ellos o no han iniciado una sesión. Esto es por que aún no se interesan en sus productos, por ejemplo, en el sector joyero, se da el caso de querer dar una sensación de exclusividad al no mostrar los precios como en el ejemplo de la imagen de abajo.

Ya sea que tengas un caso similar o no, pero quieres ocultar los precios de tus productos a usuario no registrados o que no tengan una sesión activa en tu sitio web.

Ejemplo, como ocultar precios a usuarios no registrados o sin sesión en Woocommerce

Woocommerce, Cómo ocultar precios a usuarios no registrados o sin sesión en Woocommerce.

Lo que tienes que hacer es pegar el siguiente código en tu archivo functions.php de tu tema hijo.

El código de PHP, remueve el botón de agregar al carrito y el precio en la página de la tienda y en single product page.

add_action( 'init', 'plab_hide_price_add_cart_not_logged_in' );
  
function plab_hide_price_add_cart_not_logged_in() {
   if ( !is_user_logged_in() ) {      
      remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
      remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
      remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
      remove_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 );   
      add_action( 'woocommerce_single_product_summary', 'plab_print_login_to_see', 31 );
      add_action( 'woocommerce_after_shop_loop_item', 'plab_print_login_to_see', 11 );
   }
}
  
function plab_print_login_to_see() {
   echo '<a href="' . get_permalink(wc_get_page_id('myaccount')) . '">' . __('Inicia sesión para ver precios', 'theme-name') . '</a>';
}

Fuente: WooCommerce: Hide Price & Add to Cart for Logged Out Users

CSS Grid Layout: Mejores diseños con menos código

CSS Grid Layout: Mejores diseños con menos código

En esta guía te voy a enseñar sobre CSS grid Layout y de que manera lo puedes usar en tus diseños, la verdad es que no es complicado, solo es cuestion de acostumbrarse a la sintaxis.

La primera vez que empece adentrarme en el tema, me costó mucho trabajo, ya que estaba acostumbrado a trabajar con floats y flexbox, y CSS Grid Layout es un concepto completamente nuevo que, como te digo la primera vez puede ser intimidante, pero no te preocupes aquí te voy a explicar todo lo que tienes que saber para qué empieces a usar CSS Grid en tus proyectos.

¿En qué consiste CSS Grid Layout?

CSS Grid Layout es un módulo completamente nuevo que trae un sistema de cuadrícula bidimensional a CSS por primera vez.

CSS Grid no es actualmente un estándar oficial, es un Candidate Recommendation por parte del W3C, aunque es una recomendación, los navegadores principales lo han adoptado.

Reemplaza el uso de floats, lo que genera menos y más legible código de css. Esto nos permite crear diseños mas complejos sin tantas complicaciones.

Si estas acostumbrado al sistema de grid de bootstrap… olvídate de él, con CSS Grid no estás limitado a 12 columnas, puedes usar cualquier cantidad de filas y columnas.

¿Qué es un grid o rejilla?

Un grid o rejilla, es una conjunto de cuadrados de medidas regulares, que están formados por una serie de líneas paralelas y perpendiculares a estas que se intersecan. Forman un grupo definido como columnas y filas.

CSS Grid Layout container

El elemento padre se llama grid container (Elemento padre contenedor). Todos los elementos que son hijos directos del elemento padre se llaman grid items.

Contamos además con ejes; El eje de las filas y el eje de las columnas, el eje de las columnas corresponde con el «Eje Y» y el eje de las filas con el «Eje X», Como se muestra en la siguiente imagen.

CSS Grid Layout: Ejes X y Y

Y hay más… Las líneas verticales y líneas horizontales que dividen la rejilla y separan las filas y las columnas, se llaman grid lines y se numeran automáticamente para las columnas así como para las filas, empezando por el uno, hasta el número de filas más uno, lo mismo para las columnas.

Ahora, El espacio que hay entre las filas y las columnas se llama gutter, el gutter para las filas puede ser diferente al de las columnas.

CSS Grid Layout: Grid lines and Gutter

El objetivo final es hacer la rejilla que aparece en la imagen, Para empezar vamos a crear el contenedor con sus elementos hijo.

<div class="wrapper">
  <div class="one">Uno</div>
  <div class="two">Dos</div>
  <div class="three">Tres</div>
  <div class="four">Cuatro</div>
  <div class="five">Cinco</div>
  <div class="six">Seis</div>
</div>
.wrapper {
  display: grid;
}

CSS Grid Layout: first approach

Filas y columnas del Grid

Lo que hicimos hasta el momento fue crear el contenedor con la propiedad display: grid. Ahora definimos las columnas y filas con la propiedad grid-template-rows y grid-template-columns.

Estas propiedades definen las pistas o tracks, qué es el espacio entre dos líneas de la rejilla «horizontal y/o vertical». Si es vertical se llama columna o column y si es horizontal se llama row o fila.

Grid Tacks

Para nuestro cometido necesitamos definir dos filas y cuatro columnas. Vamos a necesitar dos filas de 150px y cuatro columnas de 150px, quedaría de la siguiente forma.

Nota: Las propiedades aceptan todas las unidades conocidas: em, rem, porcentajes, pixeles, vh, vw, etc.

.wrapper {
  display: grid;
  grid-template-columns: 150px 150px 150px 150px;
  grid-template-rows: 150px 150px;
}

CSS Grid Layout: filas y columnas

Para separar las ítems uno del otro, lo podemos hacer cambiando el tamaño del gutter con la propiedad grid-row-gap para las filas y grid-column-gap para las columnas. Si quieres que el gap sea el mismo para filas y columnas, lo puedes hacer con la propiedad grid-gap.

.wrapper {
  display: grid;
  /* El mismo tamaño para filas y columnas */
  grid-gap: 25px;

  /* Diferente tamaño para filas y columnas */
  grid-row-gap: 25px;
  grid-column-gap: 50px;
}

Tamaños fijos y flexibles: la unidad fr

Hasta ahorita hemos definido las filas y columnas de forma manual, que siendo honestos no es muy práctico a la hora de trabajar en proyectos complejos (grid de 12 columnas).

CSS Grid trae consigo una función que nos va a facilitar la vida al momento de crear filas y columnas, la función se llama repeat(), esta función recibe dos argumentos: el primero es la cantidad de elementos que quieres crear y el segundo recibe el tamaño de dichos elementos.

.wrapper {
  grid-template-columns: repeat(4, 150px);
  grid-template-rows: repeat(2, 150px);
}

Al igual que la forma manual, estamos creando cuatro columnas de 150px y 2 filas de 150px, tenemos el mismo resultado con menos código ¡Genial!

Si quieres crear una nueva columna o fila con un tamaño diferente, lo haces de la siguiente forma:

.wrapper {
  grid-template-columns: repeat(3, 150px) 250px;
  grid-template-rows: repeat(2, 150px);
}

CSS Grid Layout: función repeat con columna extra al final

Como se muestra en la imagen las tres columnas definidas por la función tienen en el mismo tamaño, la cuerta es un poco más grande.

Ok, definir los tamaños de los elementos esta bien, digo, por lo general se define el ancho de un contenedor, pero hay ocasiones en las que se espera que el contenido tome la mayor cantidad de espacio que hay disponible. Esto es un poco similar a Flexbox donde la propiedad flex si la ponemos en uno se expandirá y ocupara todo el espacio posible.

CSS grid cuenta con una unidad de medida que tiene el mismo tipo de funcionamiento, se llama fractional unit o fr, esta unidad permite que un elemento se expanda y tome todo el espacio restante que tenga disponible.

El elemento va a tomar “una fracción” del espacio disponible, así si definimos el tamaño como 2fr; Va a tomar dos veces el tamaño de una fracción.

Usando 1fr en la columna final queda de la siguiente forma:

.wrapper {
  grid-template-columns: repeat(3, 150px) 1fr;
  grid-template-rows: repeat(2, 150px);
}

CSS Grid Layout: 1fr en la última columna

Debido a que nuestra rejilla tiene un tamaño de 1000px la última columna toma el espacio restante.

Ok, ¿Qué podemos hacer para que las columnas tengan el mismo tamaño? Bueno, en ese caso tendríamos que definir el tamaño en 1fr.

.wrapper {
  grid-template-columns: repeat(4, 1fr);
}

CSS Grid Layout: función repeat con 1fr

Posicionando elementos en la cuadrícula

Todos los elementos de la cuadrícula se distribuyen según el orden de origen, esto es de izquierda a derecha, podemos cambiar dicho orden y hacerlo a nuestro antojo.

Para hacer el movimiento nos tenemos que basar en las grid lines y elegir a que puntos queremos mover el elemento, por ejemplo:

CSS Grid Layout: posicionando elementos

Si queremos cambiar de posición el primer elemento y lo colocamos en lugar del elemento seis, haríamos lo siguiente en el elemento que queremos mover:

.one {
  grid-row-start: 2;
  grid-row-end: 3;
  grid-column-start: 2;
  grid-column-end: 3;
}

Con esto le estamos diciendo que para la fila, tiene que empezar en la línea 2 y terminar en la línea 3; y para las columnas empieza en la 2 y termina en la tres, queda de la siguiente forma.

CSS Grid Layout: moviendo un item

Existe una forma corta para definir la ubicación: grid-row y grid-column.

.one {
  grid-row: 2 / 3;
  grid-column: 2 / 3;
}

Con menos código tenemos el mismo resultado, el primer parámetro es donde empieza, se separan con un “/” y el segundo parámetro donde termina.

Extender Grid Items

Para abarcar elementos de la cuadrícula en varias celdas o grid cells, existen varias maneras de realizar esa tarea, por ejemplo, digamos que queremos expandir dos lugares el ítem con número dos, para eso tenemos que hacer lo siguiente:

.two {
  grid-column: 2 / 4;
}

Con esto le estamos diciendo que el elemento empieza en el grid line número dos y que se expanda hasta el grid line número cuatro, este es el resultado en imagen.

CSS Grid Layout: grid implícito

Debido a que el elemento abarca dos grid cells, entonces se hace espacio al final del grid para agregar el elemento que hace falta, el número ocho.

Otra forma de expandir determinadas posiciones es usando el keyword, span:

.two {
  grid-column: 2 / span 2;
}

Con la palabra span, le estamos indicando las posiciones que queremos que abarque, en este caso dos y tenemos el mismo resultado que con la instrucción anterior.

Hay ocasiones en las que no sabemos el espacio que puede abarcar el contenido de las ítems, y queremos que abarque todo el espacio disponible, en ese caso en lugar de especificar cuanto espacios abarcara, usamos -1 para indicarle que tome todo el espacio disponible.

.eight {
  grid-column: 1 / -1;
}

CSS Grid Layout: expandir todo el espacio

Nombres en grid lines y grid áreas

Usar números para definir los grid cells, es sencillo si tu diseño también lo es, en el mundo laboral te vas a encontrar con proyectos más complejos que otros, para esos casos lo mejor que podemos hacer es asignarles un nombre a las líneas, veamos como.

.wrapper {
  grid-template-rows: repeat(2, [row-start] 150px [row-end]);
  grid-template-columns: repeat(4, [col-start] 1fr [col-end]);
}

Dentro de la función repeat(), definimos el nombre de las filas y columnas, en el caso de las filas, definimos el inicio que se llama row-start y el final se llama row-end.

La función repeat(), básicamente es un loop, y va a crear dos filas con nombres row-start y row-end. ¿Cómo podemos manipulas las columnas independientemente? Bueno, cuando los elementos se crean dentro de la función automáticamente les asigna un número. Por ejemplo, la primera fila se llama ahora: row-start 1 y row-end 1, la segunda queda: row-start 2 y row-end 2.

Bueno, ya tenemos definidos los nombres para las filas y las columnas, ahora vamos a usarlos. Si factorizamos un poco el código usando los nombres, el código queda así:

.eight {
  grid-column: col-start 1 / col-end 4;
}

Con esto tenemos el mismo resultado de la imagen anterior, solo que ahora es mucho más sencillo posicionar los elementos en la cuadrícula.

Grid áreas

Existe otra forma de posicionar elementos que consiste en nombrar las áreas. Para nombrar “áreas” usamos la propiedad grid-template-areas en el contenedor.

.wrapper {  
  grid-template-areas: 'box-1 box-2 box-3 box-4'
                       'box-5 box-6 box-7 box-8'
}

.one {
  grid-area: box-1;
}

.two {
  grid-area: box-2;
}

.three {
  grid-area: box-3;
}

.four {
  grid-area: box-4;
}

.five {
  grid-area: box-5;
}

.six {
  grid-area: box-6;
}

.seven {
  grid-area: box-7;
}

.eight {
  grid-area: box-8;
}

Básicamente, grid-template-areas crea una representación con texto de cómo nuestro diseño final se verá. En el elemento hijo mediante la propiedad grid-area le asignamos el nombre definido en grid-template-areas y automaticamente el elemento será asignada a dicha área.

Esta técnica es práctica con diseños sencillos que no impliquen mucha complejidad, si tu diseño es muy complejo (12 columnas, header elaborado, etc.), te sugiera que no uses esta técnica, ya que se vuelve poco práctica.

Implicit Grids vs. Explicit Grids

Son las áreas que definimos manualmente y las que se generan automáticamente, para colocar todos los elementos que son.

.wrapper {
  grid-template-rows: repeat(2, [row-start] 150px [row-end]);
  grid-template-columns: repeat(2, [col-start] 1fr [col-end]);
}

En el código anterior estamos definiendo dos filas y dos columnas, nuestro diseño cuenta con 8 columnas, entonces al estar definiendo solo dos columnas y dos filas y el resto de los elementos se convierten en un grid implícito, ya que nosotros no lo definimos como tal, el mismo CSS Grid se encarga de posicionar los elementos restantes.

Implicit grid vs explicit grid

Usando min-content, max-content y la función minmax()

Max-content

.wrapper {
  grid-template-rows: repeat(2, [row-start] 150px [row-end]);
  grid-template-columns: max-content 1fr 1fr 1fr;
}

La especificación max-content se adapta al tamaño del contenido con mayor tamaño dentro del elemento, mientras 1fr hace que el elemento tome el espacio disponible, max-content toma el tamaño del elemento más grande, como se puede ver en la imagen siguiente.

CSS Grid Layout: max-content

Min-content

.wrapper {
  grid-template-rows: repeat(2, [row-start] 150px [row-end]);
  grid-template-columns: min-content 1fr 1fr 1fr;
}

La especificación min-content trabaja a la inversa, el elemento se adapta al tamaño del elemento con el contenido de menor tamaño.

CSS Grid Layout: min-content

Se puede dar el caso, por ejemplo al usar min-content, que el contenido del elemento se desborde, para esos casos hacemos uso de la función minmax().

Minmax()

Es una función que recibe dos parámetros, CSS se asegura que la fila o columna siempre se mantendrá entre estos dos valores. Por ejemplo, imagina que pasamos a la función minmax() 150 píxeles y 250 píxeles para una columna, CSS Grid Layout garantizará que, pase lo que pase, esta columna de la cuadrícula siempre permanecerá entre 150 y 250 píxeles de ancho.

.wrapper {
  grid-template-rows: repeat(2, [row-start] 150px [row-end]);
  grid-template-columns: minmax(150px, 250px) repeat(3, 1fr);
}

CSS Grid Layout: minmax()

Como se puede observar la primera columna gracias a la función minmax(), tendrá un tamaño entre 150 y 250px nomas, si cambiamos el tamaño del contenedor por un valor en porcentaje, digamos un 90% y cambias el tamaño del navegador, vas a notar que en cierto punto por más pequeña que sea la pantalla, el valor siempre se mantendrá en 150px, esto es de suma utilidad cuando queremos controlar el tamaño del contenido que tenemos, esta función también acepta los valores min-content y max-content.

Diseños responsivos: auto-fit y auto-fill

Gracias a CSS Grid, podemos tener diseños responsivos sin tener que escribir media queries, veamos como funciona auto-fit y auto-fill.

Auto-fill

Llena la fila con las columnas que puedan caber. Es decir que crea columnas siempre que quepa una nueva, ya que está tratando de llenar la fila con tantas columnas como sea posible.

.wrapper {
  grid-template-rows: repeat(2, [row-start] 150px [row-end]);
  grid-template-columns: repeat(auto-fill, 100px);
}

Las columnas recién agregadas aunque están vacías, seguirán ocupando un espacio designado en la fila.

CSS Grid Layout: auto-fill

Auto-fit

Tiene el mismo que funcionamiento que auto-fill. La diferencia es que auto-fit colapsa los espacios vacíos, como se puede ver en la siguiente imagen.

.wrapper {
  grid-template-rows: repeat(2, [row-start] 150px [row-end]);
  grid-template-columns: repeat(auto-fit, 100px);
}

Colocadas estas propiedades, a medida que va cambiando que vamos variando el tamaño de las pantallas, van a hacer que se distribuyan automáticamente.

Ahora, si nos apoyamos de la función minmax(), podemos hacer un diseño responsive, sin media queries, y con un código más ligero.

.wrapper {
  grid-template-rows: repeat(2, [row-start] 150px [row-end]);
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

Nota: Firefox y Chrome viene dotados de un visor de grid, te será de mucha utilidad al momento de escribir los estilos CSS.

See the Pen
CSS Grid Layout Example
by Plectro lab (@Plectro-lab)
on CodePen.

En resumen

CSS Grid Layout te abre un nuevo abanico de oportunidades a la hora crear diseños. Gracias a su fácil uso, ofrece un gran poder de diseños, además si lo combinas con flexbox te será mucho más sencillo crear los diseños que tengas en mente.

Esto también nos va a permitir ofrecer estilos más ligeras, que se traduce en tiempos de carga más rápido y usuarios contentos ?.

Es un poco confuso al comienzo debido a que es un cambio respecto a como veníamos manejando los diseños de las páginas web.

Definitivamente deberías de darle una oportunidad y empezar a jugar con él, actualmente es un Candidate Recommendation, aun así tiene un alto nivel de soporte por parte de los navegadores.

Si quieres investigar más al respecto, la documentación oficial te será de gran ayuda.

 

Polyfill: cubriendo las grietas en la web

Polyfill: cubriendo las grietas en la web

En esta entrada vamos a tocar un tema que muchas veces damos por sentado cuando trabajamos con frameworks o con librerías de terceros y que tienen un gran impacto al momento de diseñar una página web.

Actualmente existe una gran variedad de dispositivos para consumir contenido web, gracias a la obsolescencia programada, la brecha entre dispositivos actualizados y desactualizados (Android / iOS / Windows Phone) es abismal.

Ni hablar de Windows y Microsoft, que cada versión de sistema operativo viene con una nueva versión de navegador web, que muchas veces es difícil actualizar a no ser que cumplas con los requisitos necesarios (actualizar el sistema operativo).

Existe el caso de personas con versiones antiguas de sistemas operativos y navegadores, tan solo por el hecho de que se sienten cómodos con lo que tienen o que el ordenador que usan, es muy viejo y no es posible instalar una versión resiente de sistema operativo.

Es aquí donde entran los polyfills.

¿Qué es un polyfill?

Un polyfill o polyfiller es un módulo de código, plugin (o script) que sirve para implementar funcionalidades de HTML5 y CSS3 a navegadores antiguos (internet explorer 6, 7 y 8) que no lo admiten de forma nativa.

En la mayoría de los casos es código escrito en JavaScript, (esto no quiere decir que solo se limite a esta tecnologia) que implementa un estándar HTML5, CSS.

Otro de sus funciones es dar soporte a funcionalidades nuevas, que aún no tienen una integración nativa en el navegador.

El término fue usado por primera vez por Remy Sharp, desarrollador web y co-autor, junto con Bruce Lawson del libro Introducing HTML5 en el año 2009.

Algunos polyfills de ejemplo

Estos son algunos ejemplos de polyfills que puedes usar para tus proyectos, solo recuerda que si estás usando un framework, probablemente el polyfill que necesitas, ya venga integrado.

Core-js

Agrega funcionalidades del ECMAScript 2021 en navegadores antiguos, como las promesas, funciones de flecha, colecciones, propuestas del ECMAScript y de la W3C.

Esta librería viene integrada con Babel que se encargará de usar los módulos necesarios de core-js en tu código.

HTML5 Shiv

Script que da soporte a elementos de seccionamiento HTML5 (section y nav) en versiones de IE (Internet Explorer) de la 6 a la 9, Safari 4.x (e iPhone 3.x), y Firefox 3.x.

-prefix-free

Permite que los navegadores actuales reconozcan las versiones sin prefijos de varias propiedades de CSS3, no hay necesidad de que el desarrollador escriba todos los prefijos de los proveedores.

SessionStorage

La funcionalidad sessionStorage está disponible en los navegadores más recientes (IE8 y posteriores), pero no en IE7 y versiones anteriores.

Existe un polyfill de almacenamiento que se encarga de dar soporte a navegadores antiguos que no soportan sessionStorage.

En resumen

Son de gran ayuda al brindar soporte a versiones antiguas de navegadores, y buenos para unificar el soporte a nuestros proyectos.

Si estás trabajando con un framework como Angular 2+, React o Vue. En ese caso el mismo framework ya tiene inlcuido su set de polyfills, lo que es de gran ayuda, ya que nos permite centrarnos en la solución principal y dejar la compatibilidad al framework.

En caso de que no trabajes con algun framework. En el GitHub de Modernizr, hay una colección de plugins, seguro ahí encuentras la solución de código que necesitas.

Clip path: crea diseños asombrosos con esta propiedad

Clip path: crea diseños asombrosos con esta propiedad

En este artículo vamos a hablar sobre la propiedad clip path, aprenderás técnicas modernas de CSS para crear diseños y efectos vanguardistas.
Desde los inicios nos han acostumbrado a que todo debe ser rectangular, no me malentiendan. Los rectángulos están bien, no tengo nada contra ellos, de hecho son de gran utilidad al momento de definir la estructura del sitio.

Solo creo que para hacer diseños que te destaquen de la competencia, a veces es necesario salir de los esquemas y apostar por algo nuevo.

Antes de esta propiedad, si querías cambiar la forma de alguna sección de tu web, tenías que hacer malabares con los pseudo elementos before y/o after, posiciones absolutas, usar imágenes…

Ya no tiene por qué ser así, clip path nos facilita la vida al momento de crear figuras o efectos que llaman la atención.

¿Cómo funciona la propiedad clip path?

La propiedad clip-path recorta o “delimita” una porción de elementos SVG, imágenes o cualquier elemento HTML. Esta propiedad viene a sustituir la obsoleta clip: clip: rect(), de CSS2.

El trazado de recorte o clipping path se define por medio de patrones, formas o polígonos.

Este trazo de recorte es una región donde todo lo que está “dentro” de esta zona es visible y todo lo que está “fuera” de esta zona no se dibuja.

ejemplo de la propiedad clip-path

El patrón de recorte (centro) se aplica a la figura con diferentes colores (izquierda). Esto da como resultado una figura recortada (derecha).

Sintaxis

La forma correcta de escribir esta propiedad es la siguiente:

clip-path: <clip-source> | [ <basic_shape> || <geometry_box> ] | none

<clip-source>: La URL que haga referencia a un elemento SVG <clipPath> interno o externo.

clip-path: url(resources.svg#blob);

<basic shape>: Acepta las formas definidas en la especificación de formas de CSS. Una forma básica utiliza el cuadro de referencia especificado para dimensionar y colocar la forma básica. Si no se especifica ningún cuadro de referencia, el cuadro de borde (border-box) se utilizará como cuadro de referencia.

Las formas que acepta son las siguientes: inset(), circle(), ellipse(), polygon() y path():

clip-path: inset(100px 50px);
clip-path: circle(50px at 0 100px);
clip-path: ellipse(50px 60px at 0 10% 20%);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
clip-path: path('M0.5,1 C0.5,1,0,0.7,0,0.3 A0.25,0.25,1,1,1,0.5,0.3 A0.25,0.25,1,1,1,1,0.3 C1,0.7,0.5,1,0.5,1 Z');

<geometry-box>: Si se usa en combinación con <basic-shape>, proporciona el box de referencia para <basic-shape>. Si se especifica por sí mismo, utiliza los bordes del cuadro especificado, incluida cualquier forma de esquina (border-radius), como ruta de recorte. Geometry-box puede tener uno de los siguientes valores:

  • margin-box: utiliza el margin box como el cuadro de referencia.
  • border-box: utiliza el border box como cuadro de referencia.
  • padding-box: utiliza el padding box como cuadro de referencia.
  • content-box: utiliza el content box como cuadro de referencia.
  • fill-box: utiliza el cuadro delimitador del objeto como cuadro de referencia.
  • stroke-box: Utiliza el cuadro delimitador de trazo como cuadro de referencia.
  • view-box: Utiliza el viewport SVG más cercano como cuadro de referencia.
  • none: No se crea ningún trazado de recorte.
clip-path: margin-box;
clip-path: border-box;
clip-path: padding-box;
clip-path: content-box;
clip-path: fill-box;
clip-path: stroke-box;
clip-path: view-box;

En este ejemplo, el círculo usaría el content-box como cuadro de referencia.

.caja {
  clip-path: circle(50%) content-box;
}

Actualmente, los navegadores no admiten el uso de valores de cuadro para la propiedad clip-path. Sin embargo, son compatibles con shape-outside.

Ahora, veamos la función polygon(), que se ve así:

img {
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}

Le estamos diciendo que todas las imágenes serán recortadas en forma de triángulo equilatero, la forma se la damos por medio de los vértices (x, y), la siguiente imagen lo ilustra mejor:

vertices en clip path

La primera coordenada determina la posición en el eje x, la segunda especifica la posición en el eje y. Los puntos están trazados en sentido de las manecillas del reloj.

Nota: no sucede así en el caso que el polígono tenga 3 pares de valores, como es el caso del triángulo de la imagen.

El primer valor se localiza a la mitad del eje x, por lo que su coordenada es 50%, para el eje y tiene un valor de 0%.

clip path función polygon

Usando las formas básicas

Como mencionamos arriba clip path acepta las formas: inset(), circle(), ellipse(), polygon().

Circle

La función circle() se define con la siguiente sintaxis: circle(radio en posX posY). La posición es opcional y está predeterminada en 50% 50%.

.circulo1 {
  clip-path: circle(50%);
}
.circulo2 {
  clip-path: circle(70% at 70% 20%);
}
Imagen para ejemplos con clip-path y las formas básicas

Ellipse

La función ellipse() se define de la siguiente forma: ellipse(radioX radioY at posX posY). La posición es opcional y está predeterminada en 50% 50%.

.ellipse1 {
  clip-path: ellipse(50% 35%);
}
.ellipse2 {
  clip-path: ellipse(50% 65% at 70% 50%);
}
gato ejemplo con clip-pathgato ejemplo con clip-path

Inset

Con la función inset() puedes definir un rectángulo, todo lo que quede fuera de esa área, desaparece. También es posible redondear las esquinas con la palabra border radius:

.inset1 {
  clip-path: inset(20% 25% 20% 10%);
}
.inset2 {
  clip-path: inset(45% 0 33% 10% round 10px);
}
gato ejemplo con clip-pathgato ejemplo con clip-path

Polygon

Con esta forma puedes crear una gran variedad de figuras, al ser un polígono puedes especificar cualquier cantidad de puntos. Se requieren al menos tres vértices para definir un polígono. Acepta pares de coordenadas en X y Y, lo valores que pueden tomar son: píxeles, porcentajes, ems, rems, etc.

.triangle {
  clip-path: polygon(50% 0, 0 100%, 100% 100%);
}
.right-arrow {
  clip-path: polygon(0% 20%, 60% 20%, 60% 0%, 100% 50%, 60% 100%, 60% 80%, 0% 80%);
}
.octagon {
  clip-path: polygon(30% 0%, 70% 0%, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0% 70%, 0% 30%);
}
.close {
  clip-path: polygon(20% 0%, 0% 20%, 30% 50%, 0% 80%, 20% 100%, 50% 70%, 80% 100%, 100% 80%, 70% 50%, 100% 20%, 80% 0%, 50% 30%);
}

See the Pen
Clip path
by Plectro lab (@Plectro-lab)
on CodePen.

Usando con un elemento SVG

Además de recortar con las figuras básicas, puedes hacer uso de un vector SVG para hacer los recortes.

<svg width="0" height="0">
  <defs>
    <clipPath id="blob">
      <polygon points="15,99 30,87 65,99 85,55 122,57 184,73 198,105
      199,150 145,159 155,139 126,120 112,138 80,128 39,126
      24,104"/>
    </clipPath>
  </defs>
</svg>

Trabaja con las mismas propiedades que usamos en CSS, cada par de coordenadas separadas por comas representa un punto del polígono.

Ahora puedes aplicar la forma definida en la función url(), usando el id definido en el elemento <clipPath>:

.clipped {
  clip-path: url(#blob);
}

See the Pen
Clip path SVG
by Plectro lab (@Plectro-lab)
on CodePen.

Animaciones y transiciones

Las animaciones y transiciones también se pueden aplicar con clip-path para crear efectos interesantes. Solo asegúrate de que todos los pasos de tu animación contengan la misma cantidad de pares de puntos.

See the Pen
Clip path animation
by Plectro lab (@Plectro-lab)
on CodePen.

Soporte en navegadores en 2021

Al momento de escribir estas líneas, la propiedad clip path tiene un excelente soporte para navegadores.

Sí deseas ofrecer soporte a navegadores antiguos, una alternativa puede ser permitir que el navegador ignore la propiedad clip-path y muestre la imagen sin recortar. Otra alternativa, puedes probar la propiedad con @supports de css y ofrecer un diseño alternativo para los navegadores que no son compatibles.

@supports(clip-path: circle(45%)) {
  /* soporte para clip-path */
}

Al principio el trabajar con la propiedad clip path puede ser intimidante, pero una vez ubicas la forma en que opera con elementos SVG y conoces el sentido de los pares de valores para la función polygon(), verás que es muy sencillo. Echa a valor la imaginación y atrévete a crear diseños únicos.

Para más información: