Gráficos circulares (Pie Charts) en puro Css.

Cómo hacer un gráfico circular (Pie Charts) en puro Css.

Gráficos circulares (Pie Charts) en puro Css.

Por Kseso ✎ 14
Gráfico circular en puro Css
Gráfico Circular puro Css.

La representación de datos en gráficos siempre es una ayuda para comprender y asimilar la información. Y los ejemplos realizados con puro Css, tanto los de barras como lineales, son ya veteranos.

Quizás de los que no haya tantas realizaciones sean de los gráficos circulares (en quesitos) hechos en puro Css. Así que este artículo va de un par de demos para hacer estos gráficos circulares. Como el de la imagen de la derecha.

Si eres de los que no te gusta jugar con Css tienes otras opciones (además de preguntarte cómo has llegado aquí) como puede ser la aplicación de Google Chart Wizard o aplicaciones de escritorio: hojas de cálculo o programas de edición vectoriales.

Gráfico circular Css con clip: rect()

Esta forma la encontré en el blog de Kyle Larson. El valor añadido por mi es el poder escalar el tamaño del gráfico de forma sencilla, que vemos al llegar ello.

Otra particularidad de esta realización es que puedes añadir sombra o borde. Y que la posición y tamaño de las porciones (que por aquello del trivial yo llamo "quesitos" en el código) es relativamente sencilla de entender y por lo tanto de aplicar. Tiene su lógica.

Gráfico circular Css por Kyle Larson

O veo la demo o no sigo leyendo

Lo primero es crear nuestro contenedor general para el gráfico y un elemento extra para aplicar un par de efectos: borde homogéneo y sombra:

* { box-sizing: border-box; } .grafico { height: 200px; margin: 1rem auto; position: relative; width: 200px; } .sombra { background-color: #fff; border-radius: 50%; box-shadow: 0 4px 7px rgba(0, 0, 0, 0.3); border: 5px solid #000; height: 100%; position: absolute; width: 100%; } <div class="grafico"> <div class="sombra"></div> <!-- aquí irán las porciones --> </div>

Todo los tamaños, tanto del gráfico como de los segmentos (no su arco) están en función de las medidas de .grafico y se colocan respecto a él al estar posicionado. Se le podrían declarar a esta caja el border-radius y overflow: hidden y así evitarnos tener que redondear cada porción, pero nos impediría aplicar el efecto de la sombra y afectaría a la hora de situar los segmentos.

El div .sombra es sólo a efectos ornamentales, así que si quieres puedes prescindir de él.

El primer segmento del gráfico circular Css

Cada porción se consigue con dos elementos enlazados:

<div class="grafico"> <div class="sombra"></div> <div id="porcion1" class="recorte"> <div class="quesito" data-rel="70"></div> </div> </div>

Las clases .recorte | .quesito son comunes a todos los segmentos que se creen. El id #porcionX cambia de quesito a quesito, siendo la que definirá su cuerda (tamaño), ubicación en el gráfico, el giro para su correcta colocación, background y otras particularidades de cada uno.

.recorte { border-radius: 50%; clip: rect(0px, 200px, 200px, 100px); position: absolute; height: 100%; width: 100%; } .quesito { border-radius: 50%; clip: rect(0px, 100px, 200px, 0px); position: absolute; height: 100%; width: 100%; } #porcion1 { transform: rotate(0deg); } #porcion1 .quesito { background-color: rgba(0,0,255,.7); transform: rotate(70deg); }
Primer segmento del gráfico circular en puro Css
1er segmento Gráfico Css.

En esta demo la magia corre por cuenta de la propiedad clip: rect() Los valores utilizados en el paréntesis hacen un recorte en recto de cada div. El resultado de la combinación de los 2 recortes (padre e hijo) es el "quesito" o porción triangular con la base redondeada.

El mayor o menor espacio ocupado (valor) de cada porción se obtiene con el valor del giro dado a cada uno. Por eso el usar un id: #porcion1 .quesito{transform: rotate(70deg);}

Y la posición que ocupa cada uno de ellos en el círculo se controla con ayuda del giro dado: #porcion1 {transform: rotate(0deg);}.

A continuación sólo es cuestión de añadir tantas porciones como necesitemos para completar el gráfico, teniendo en cuenta tres detalles:

  1. Que la suma total del valor de los giros de todos los #porcionX .quesito debe ser 360. Si es menos habrá espacios vacíos y si más solapamientos.
  2. En las porciones de la parte izquierda del gráfico circular con Css (semicírculo izquierdo) conviene hacer el giro al contrario, esto es en valor negativo o contrario al giro de las agujas del reloj.
  3. La lógica para colocar cada quesito adyacente al precedente es que su punto de colocación (valor del giro de #porcionX+1 es la suma de los dos giros del que le precede = #porcionX + (#porcionX .quesito).

Lo valores de cada porción del gráfico

Una vez declaradas todas las porciones y colocadas en su lugar, sólo nos resta un detalle para que los valores de cada una se muestren también.

Para ello nos añadimos un atributo a cada quesito con su valor del tipo data-*. Así queda el marcado html de cada parte del gráfico Css, ya completo:

<div id="porcion3" class="recorte"> <div class="quesito" data-rel="25"></div> </div>

Y para mostrarlo utilizamos en el pseudoelemento ese atributo y su valor en la propiedad content. Junto a unas declaraciones a mayores para posicionarlo sobre su color y contrarrestando el giro según el gusto o la necesidad de cada caso:

#porcion3 .quesito:after { content: attr(data-rel); position: absolute; left: 35%; top: 4%; transform: rotate(70deg); }

Y el resultado final, todo junto y con los prefijos privativos necesarios, así es como luce el gráfico circular en puro Css ya completo:

Check out this Pen!

Ramajero Argonauta, Enredique Amanuense de CSS.
#impoCSSible inside
Dicen que, en español, EsCss es el mejor blog de CSS. Posíblemente exageren.
@Kseso EsCss Don Kseso Kseso

Comentarios: 14

  1. Interesante, muchas gracias.

    ResponderEliminar
  2. Creo que me perdí el artículo donde se explicaba clip: rect(); xD

    ResponderEliminar
  3. Parece ser que los límites de CSS están solo en la imaginación

    Buen articulo, y en general excelente blog :D

    ResponderEliminar
  4. Súper el aporte!!, que buen blog!!

    ResponderEliminar
  5. Creo que no funciona si alguna de las porciones mide más de 180 grados

    ResponderEliminar
    Respuestas
    1. ¿Si algún porcentaje fuese mayor a 50%?
      Hay que crearlo con más de una capa, obviamente. Pero no entiendo por qué no funcionaría.
      De hecho, si al ejemplo le cambiamos

      #porcion1 .quesito {
      background-color: rgba(255,255,0,.7);
      transform: rotate(70deg);
      }


      ya hay un ... (¿cómo le dice? ¡ah, sí!) "quesito" amarillo de más de 50%. Habrá que ajustar los números, pero se ve claramente que es posible.

      Eliminar
    2. Hola Diego.
      Si te fijas, los quesitos están logrados en base a la propiedad clip que produce cortes rectos a 90º.
      Recorta el sobrante de la caja generada. Por lo tanto no esperes obtener un trozo a mayores "por fuera".

      Pero si tienes necesidad de mostrar una "porción" mayor a un semicírculo siempre puedes suplir con algo de imaginación lo que Css no permite.
      Bastaría con usar el espacio libre del div "gráfico" para tener una porción mayor de 180º siempre que la suma del resto de "quesitos" cubran menos de la mitad.

      Un saludo

      Eliminar
    3. Aquí tienes un fork del pen del artículo.
      Creo que queda más claro que la explicación confusa de mi respuesta anterior.

      Un saludo

      Eliminar
  6. Hola.

    No entiendo porque si le doy 350px de ancho y alto, se desarma todo y es re dificil porder volver a armarlo :(

    Saludos.

    ResponderEliminar
    Respuestas
    1. Si pudieras publicar tu código o un enlace* a tu realización sería posible ver qué ocurre con ella.
      De esta forma, imposible, Roddy, una respuesta precisa y concreta a tu caso.

      Sólamente recordarte que hay que controlar, además del tamaño, el valor de clip y el giro de cada uno de los "quesitos".

      Un saludo

      * Recuerda que puedes publicar código o insertar pens de Codepen

      Eliminar
    2. Muchas gracias por la respuesta.

      te dejo aqui el link http://dev.axionla.cl/infografia/ al estilo .grafico le di 350px de ancho y 350px de alto, al hacerlo los pedazos se desarman, y al tratar de manipular "clip: rect(0px, 200px, 200px, 100px)" no puedo lograr llegar a encajarlos, no se si logro explicarme.

      un Saludo.

      Eliminar
    3. Creo que con el siguiente pen podrás observar la relación entre el tamaño de .grafico y los valores de la propiedad clip de .recorte y .quesito

      Lo mimo ocurre con el resto de las relaciones (tamaños y ubicación de cada porción) con los giros declarados.
      Pero todo esto lo tienes detallado en el artículo.

      Un saludo.

      [pen]data-height="400" data-theme-id="299" data-slug-hash="QjLvRm" data-default-tab="result" data-user="Kseso" class='codepen'[/pen]

      Eliminar
    4. Oh muchisimas gracias.

      ahora logre entender viendo el CSS, y gracias por ayudarme con esto. me saco de un apuro.

      gracias por enseñar y por subir informacion valiosa para nosotros. siempre veo este blog.

      Saludos.

      Eliminar

EsCss RSS del Blog RSSS Comentarios Humans.txt ᛯ Diseno por Kseso SiteMap