Herramientas de usuario

Herramientas del sitio


clase:daw:diw:css-responsivo

¡Esta es una revisión vieja del documento!


4. CSS: Responsivo

En anteriores temas hemos visto como con grid y flex ya podíamos hacer algunas cosas que se ajustaran al tamaño de la pantalla, lo que llamamos responsivo. En este tema vamos a ver mas formas de hacer responsivo una página.

Mas información:

Responsivo vs Adaptativo

Hacer un diseño responsivo es que la misma página se adapte a distintos tamaños de pantalla. Hacer un diseño adaptativo es hacer páginas distintas según el tamaño de la pantalla.

Ejemplo de diseño adaptativo es la página de AliExpress:

La ventaja de las webs adaptativas es que en la versión móvil solo se cargan las cosas que se necesitan para el movil además de que está hecha pensando en móvil. El inconveniente es que hay que desarrollar dos páginas.

viewport

Añadir a todas las páginas la siguiente línea en el <head> del HTML

<meta name="viewport" content="width=device-width, initial-scale=1">

Con esto se consigue que la página tenga el tamaño del dispositivo, ya que sino se pone , el dispositivo podría hacer que la página se haga mas grande y crear barras de desplazamiento.

Mas información:

Unidades

View Port

Podemos hacer ciertos tamaños que sean en función del tamaño de la pantalla. Para ello se usan las unidades como vw o vh que hacen referencia al tamaño de la pantalla. CSS Viewport Units: A Quick Start

  • vh Es la altura de la ventana. Un valor de 1vh es igual al 1% del alto.
  • vw Es el ancho de la ventana. Un valor de 1vw es igual al 1% del ancho.
  • vmin Mínimo entre el ancho y el alto. Es la dimensión más pequeña de la ventana. Si el alto de la ventana gráfica es menor que el ancho, el valor de 1vmin será igual al 1% de la altura. De manera similar, si el ancho es menor que la altura, el valor de 1vmin será igual al 1% del ancho.
  • vmax Máximo entre el ancho y el alto. Es la dimensión más grande de la ventana. Si el alto de la ventana gráfica es mayor que el ancho, el valor de 1vmin será igual al 1% de la altura. De manera similar, si el ancho es mayor que la altura, el valor de 1vmin será igual al 1% del ancho.

.titulo {
    font-size: 10vw;
}

<p class="titulo">Hola mundo</p> 

En el ejemplo anterior, el tamaño de la fuente se hace mas grande a medida que se hace mas ancha la ventana.

Podemos pensar que 100vw es similar a 100%, pero hay dos diferencias Difference between Width:100% and width:100vw?.

  • 100% hace referencia al tamaño de donde está el elemento donde estamos , no al tamaño de la ventana.
  • 100% no incluye el tamaño de las barras de desplazamiento , mientras que 100vw si que lo hace.

Para ésto último a veces se hace lo siguiente:

.ejemplo {
   width: 100vw;
   height: 100vw;
   max-width: 100%;
}

  • También se pueden usar decimales con vw o vh

.titulo {
    font-size: 3.14vw;
}

rem

La unidad rem hace referencia al tamaño de fuente del HTML. El tamaño en píxeles se obtiene de multiplicar el valor de rem por el tamaño de la fuente de la página

html {
   font-size:12px;
}

Otra forma de cambiar el font-size por defecto es configurar el tamaño de 1rem en el propio navegador. Lo suele hacer gente con diversidad visual. En chrome es en "Configuración --> Aspecto --> Personalizar fuentes"

Veamos ahora como se usa rem en bootstrap para los botones:

Tamaño botón Tamaño de fuente Padding horizontal Padding vertical
Normal 1rem 0.75rem 0.375rem
Grande btn-lg 1.25rem 1rem 0.5rem
Pequeño btn-sm 0.875rem 0.5rem 0.25rem

Vamos ahora los mismo datos pero en px suponiendo que el tamaño de fuente es 16px.

Tamaño botón Tamaño de fuente Padding horizontal Padding vertical
Normal 16px 12px 6px
Grande btn-lg 20px 16px 8px
Pequeño btn-sm 14px 8px 4px

Y por último veamos la relación que hay entre en padding y el tamaño de fuente en %

Tamaño botón Padding horizontal respecto
del tamaño de fuente
Padding vertical respecto
del tamaño de fuente
Normal 75% 37,5%
Grande btn-lg 80% 40%
Pequeño btn-sm 57,142% 28,571%

Resulta que no hay una relación constante entre el tamaño de la fuente y el tamaño del padding.

Es decir para un tamaño normal el padding horizontal es el 75% del tamaño de la fuente pero en un botón grande (que el tamaño de fuente es más grande) el padding horizontal es el 80% del tamaño de la fuente y para terminar en un botón pequeño el padding horizontal es el 57% del tamaño de la fuente. ¿No debería ser constante el tamaño del padding respecto del tamaño de fuente? Por lo tanto si aumentamos el tamaño de fuente en el navegador , los padding no deberían aumentar proporcionalmente sino como vemos que lo hace bootstrap.

em

La unidad em hace referencia al tamaño de fuente del elemento donde está. El tamaño en píxeles se obtiene de multiplicar el valor de em por el tamaño de la fuente de ese elemento

Mi recomendación es usar siempre px y cambiar los tamaños según la pantalla con media queries.

Mas informnación:

Cálculos en CSS

Podemos usar funciones en CSS para calcular valores.

min()

Retorna el mínimo de los dos valores.

.titulo {
    font-size: min(100px,10vw);
}
<p class="titulo">Hola mundo</p> 

En el ejemplo el tamaño máximo de la fuente nunca será mayor que 100px por mucho que se haga grande la ventana.

max()

Retorna el máximo de los dos valores.

.titulo {
    font-size: max(40px,10vw);
}
<p class="titulo">Hola mundo</p> 

En el ejemplo el tamaño mínimo de la fuente nunca será menor que 40px por mucho que se haga pequeña la ventana.

clamp()

Retorna un valor pero sin ser menos que un mínimo ni mayor que un máximo

.titulo {
    font-size: clamp(40px,10vw,100px);
}
<p class="titulo">Hola mundo</p> 

En el ejemplo el tamaño mínimo de la fuente nunca será menos que 40px por mucho que se haga pequeña la ventana ni será mayor que 100px por mucho que se haga grande la ventana.

Mas información:

calc()

Permite hacer cálculos en CSS

.titulo {
    font-size: calc(10vw - 10px);
}

.titulo {
    font-size: calc( ( 1 / 3 ) * 100vw);
}

.titulo {
    font-size: clamp(40px,10vw - 10px,100px);
}

Dentro de clamp se pueden hacer cálculos directamente sin necesidad de usar calc.
Es obligatorio separar siempre las operaciones de suma y resta con espacios en blanco de sus operandos.

Por ejemplo, la siguiente expresión no es correcta:

calc(50%-8px)

debiendose corregir y quedando así:

calc(50% - 8px).

Aunque los operadores * y / no necesitan espacio en blanco, se sugiere agregarlos por razones de consistencia.

<p class="titulo">Hola mundo</p> 

Calculo de valores con clamp

La siguiente gráfica muestra como funciona clamp(200px, 59.88vw + 0.5988px, 400px).

Para calcular los tamaños de pantalla donde se producen los cambios (puntos rojos) las variable son las siguientes:

  • $w_{lower}$: El ancho de pantalla para el valor mínimo que es 333px.
  • $w_{upper}$: El ancho de pantalla para el valor máximo que es 667px.
  • $min_{value}$: El valor mínimo de la propiedad CSS que es 200px.
  • $max_{value}$: El valor máximo de la propiedad CSS que es 400px.


  • $pendiente$: El valor que se pone en vw que es 59.88vw.
  • $coeficiente_{posición}$: Es el valor que se suma a la pendiente en px que es 0.5988px.

Pero, ¿como calculamos los valores de $pendiente$ y $coeficiente_{posición}$?.

De forma genérica podemos establecer los valores de las 4 variables de la siguiente forma:

Siendo los valores de $pendiente$ y $coeficiente_{posición}$ los siguientes:

$$ pendiente=\frac {max_{value} - min_{value}}{w_{upper} - w_{lower}} \cdot 100 \\ coeficiente_{posición}=min_{value} - \frac{pendiente}{100} \cdot w_{lower} $$

Veamos el ejemplo en el que queremos que la propiedad font-size siga estas reglas:

  • $w_{lower}$: 230px
  • $w_{upper}$: 600px
  • $min_{value}$: 12px
  • $max_{value}$: 20px

Entonces

$$ pendiente=\frac {max_{value} - min_{value}}{w_{upper} - w_{lower}} \cdot 100=\frac {20-12}{600-230} \cdot 100=2,1621622 \\ coeficiente_{posición}=min_{value} - \frac{pendiente}{100} \cdot w_{lower}=12-\frac{2,1621622}{100} \cdot 230=7,02702694 $$

Por lo tanto el css será:

.titulo {
    font-size: clamp(12px,2.1621622vw + 7.02702694px,20px);
}

En la primera figura

cuyos valores eran:

  • $w_{lower}$: 333px
  • $w_{upper}$: 667px
  • $min_{value}$: 200px
  • $max_{value}$: 400px

Entonces

$$ pendiente=\frac {max_{value} - min_{value}}{w_{upper} - w_{lower}}\cdot 100=\frac {400-200}{667-333} \cdot 100=59.88024 \\ coeficiente_{posición}=min_{value} - \frac{pendiente}{100} \cdot w_{lower}=200-\frac{59.88024}{100} \cdot 333=0.5988 $$

Por lo tanto el css será:

.titulo {
    font-size: clamp(200px, 59.88vw + 0.5988px, 400px);
}

  • El código en python para crear los gráficos es el siguiente:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import AutoLocator

min_value=200
max_value=400
pendiente=59.88
coeficiente_posición=0.5988  #b

def decore_axes(axes,title,xlabel,ylabel):
  axes.set_title(title, fontsize=14,pad=5,color="#000000")
  axes.set_xlabel(xlabel, fontsize=10,labelpad=5,color="#003B80")
  axes.set_ylabel(ylabel, fontsize=12,labelpad=5,color="#003B80")
  axes.set_xlim(xmin=0)
  axes.grid(visible=True, which='major', axis='both',color="#FFFFFF",linewidth=1)
  axes.set_axisbelow(True)
  axes.yaxis.set_major_locator(AutoLocator())
  axes.set_facecolor('#E9F0FC')

max_w_size=1200
x=np.linspace(0,max_w_size,3000)
y=[]

for xi in x:
  yi=xi*(pendiente/100)+coeficiente_posición
  if (yi<min_value):
    yi=min_value
  elif (yi>max_value):
    yi=max_value

  y.append(yi)

min_corte_x=((min_value-coeficiente_posición)*100)/pendiente
max_corte_x=((max_value-coeficiente_posición)*100)/pendiente
figure=plt.figure(figsize=(8,4))
axes = figure.add_subplot(1,1,1)

axes.plot(x,y)
axes.scatter(min_corte_x,min_value,c="red", zorder=2)
axes.scatter(max_corte_x,max_value,c="red", zorder=2)

decore_axes(axes,f"clamp({min_value}px,{pendiente}vw + {coeficiente_posición}px,{max_value}px)","Tamaño pantalla","Valor propiedad CSS")

_=axes.set_xticks( [0,min_corte_x,max_corte_x,max_w_size])

Imágenes

Hay muchas opciones al respecto de las imágenes responsivas. La técnica consiste principalmente en usar una imagen u otra en función de:

  • Ancho o alto del dispositivo
  • Pixel-ratio del dispositivo
  • Tipos soportados por el navegador.

Una explicación completa la puedes ver en el siguiente enlace: Responsive Images.

Aquí solo vamos a ver como carga una imagen u otra en función del ancho del dispositivo.

Veamos un ejemplo: Según la resolución , no queremos cargar siempre la misma imagen sino que cambiamos la perspectiva de la foto ya que tenemos menos sitio.

  • Pantallas grandes:

  • Pantallas medianas:

  • Pantallas pequeñas:

<picture>
  <source media="(min-width: 900px)" srcset="https://logongas.es/lib/exe/fetch.php?media=responsive-large.jpg" />
  <source media="(min-width: 500px)" srcset="https://logongas.es/lib/exe/fetch.php?media=responsive-medium.jpg" />  
  <img src="https://logongas.es/lib/exe/fetch.php?media=responsive-small.jpg"  />
</picture>

Tablas

Para hacer tablas responsivas, realmente lo único que podemos hacer es que haya barras de Scroll. Para eso ponemos un div sobre la tabla con la propiedad overflow: auto;

<html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <style>
            .tabla-scroll {
              overflow: auto;
            }
            .ancho-min-100 {
              min-width: 100px;
            }
            .ancho-min-150 {
              min-width: 150px;
            }
            .ancho-min-200 {
              min-width: 200px;
            }
            .ancho-max-100 {
              max-width: 100px;  
            }
            .ancho-max-150 {
              max-width: 150px;  
            }
            .ancho-max-200 {
              max-width: 200px;  
            }

            .ancho-100 {
              width: 100px;
              min-width: 100px;  
            }
            .ancho-150 {
              width: 150px;
              min-width: 150px;  
            }
            .ancho-200 {
              width: 200px;
              min-width: 200px;  
            }
        </style>
    </head>
    <body>
        <h1 >Ejemplo de tablas responsivas</h1>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

        <div class="tabla-scroll">
            <table>
            <thead>
              <tr>
                <th class="ancho-min-150 ancho-max-200">Author</th>
                <th class="ancho-min-150 ancho-max-200 ">Title</th>
                <th class="ancho-min-100 ancho-max-150">Year</th>
                <th class="ancho-200">ISBN-13</th>
                <th class="ancho-150">ISBN-10</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>Miguel De Cervantes</td>
                <td>The Ingenious Gentleman Don Quixote of La Mancha</td>
                <td>1605</td>
                <td>9783125798502</td>
                <td>3125798507</td>
              </tr>
              <tr>
                <td>Gabrielle-Suzanne Barbot de Villeneuve</td>
                <td lang="fr">La Belle et la Bête</td>
                <td>1740</td>
                <td>9781910880067</td>
                <td>191088006X</td>
              </tr>
              <tr>
                <td>Sir Isaac Newton</td>
                <td>The Method of Fluxions and Infinite Series: With Its Application to the Geometry of Curve-lines</td>
                <td>1763</td>
                <td>9781330454862</td>
                <td>1330454863</td>
              </tr>
              <tr>
                <td>Mary Shelley</td>
                <td>Frankenstein; or, The Modern Prometheus</td>
                <td>1818</td>
                <td>9781530278442</td>
                <td>1530278449</td>
              </tr>
              <tr>
                <td>Herman Melville</td>
                <td>Moby-Dick; or, The Whale</td>
                <td>1851</td>
                <td>9781530697908</td>
                <td>1530697905</td>
              </tr>
              <tr>
                <td >Emma Dorothy Eliza Nevitte Southworth</td>
                <td>The Hidden Hand</td>
                <td>1888</td>
                <td>9780813512969</td>
                <td>0813512964</td>
              </tr>
              <tr>
                <td>F. Scott Fitzgerald</td>
                <td>The Great Gatsby</td>
                <td>1925</td>
                <td>9780743273565</td>
                <td>0743273567</td>
              </tr>
              <tr>
                <td>George Orwell</td>
                <td>Nineteen Eighty-Four</td>
                <td>1948</td>
                <td>9780451524935</td>
                <td>0451524934</td>
              </tr>
              <tr>
                <td>Nnedi Okorafor</td>
                <td>Who Fears Death</td>
                <td>2010</td>
                <td>9780756406691</td>
                <td>0756406692</td>
              </tr>
            </tbody>
        </table>
    </div>

    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    
    </body>

</html>

Mas información:

CSS Media Queries

Permiten tener un CSS distinto según el tamaño de la pantalla

.titulo {
    font-size: 40px;
}

 
@media (min-width: 576px) {
    .titulo {
        font-size: 50px;
    }
}
 
@media (min-width: 768px) {
    .titulo {
        font-size: 55px;
    }
}
 
@media (min-width: 992px) {
    .titulo {
        font-size: 70px;
    }
}

<p class="titulo">Hola mundo</p>     

Como vemos para cada resolución se usa un CSS distinto y por lo tanto el tamaño es distinto según la resolución.

Véase como el CSS por defecto es para tamaños menores de 576px. Es lo que se llama Mobile First Design. Es decir que por defecto el CSS es para móviles y luego ya se añade CSS para otros tamaños. En el ejemplo se usan los mismos anchos que en los breakpoints de Bootstrap.

Breakpoints

Al hacer las media queries hay que decidir a partir de qué ancho cambia cada pantalla. En los siguientes artículos se indica cuáles se usan en diversos frameworks CSS.

  • Bootstrap
Nombre Descripcion Ancho Mínimo
-- Extra small devices (portrait phones) none
sm Small devices (landscape phones) 576px
md Medium devices (tablet) 768px
lg Large devices (desktops) 992px
xl Extra large devices (large desktops) 1200px
xxl Extra Extra large devices (extra large desktops) 1400px
  • Tailwind
Nombre Ancho Mínimo
sm 640px
md 768px
lg 1024px
xl 1280px

menu.zip

    <div class="menu">
        <ul class="menu-items menu-items-oculto">
            <li class="menu-item"><a href="#home">Home</a></li>
            <li class="menu-item"><a href="#news">News</a></li>
            <li class="menu-item"><a href="#contact">Contact</a></li>
            <li class="menu-item"><a href="#about">About</a></li>
        </ul>
        <a href="javascript:void(0);" class="menu-hamburguesa" onclick="toggleVisibilityMenu()">☰</a>
    </div>
    <h1 style="text-align: center">Mi empresa</h1>
    <p style="height: 1200px;width: 500px;"></p>

        .menu {
            display: flex;
            flex-direction: row;
        }

        @media (max-width: 499px) {
            .menu {
                position: fixed;
                top: 0;
                left: 0;
            }
        }

        .menu-hamburguesa {
            display: none;
        }
        @media (max-width: 499px) {
            .menu-hamburguesa {
                display: block;
            }
        }




        .menu-items {
            display: flex;
            flex-direction: row;
        }
        @media (max-width: 499px) {
            .menu-items {
                flex-direction: column;
            }
        }


        .menu-item {
            padding: 10px;
            color: #ffffff;
            background-color: #c0c0c0;
        }
        @media (max-width: 499px) {
            .menu-item {
                padding-left: 2px;
                background-color: #00ff00;
            }
        }


        @media (max-width: 499px) {
            .menu-items-visible {
                display: block;
            }

            .menu-items-oculto {
                display: none;
            }
        }

        function toggleVisibilityMenu() {
            var itemsElements = document.getElementsByClassName("menu-items");
            var hamburgerElements = document.getElementsByClassName("menu-hamburguesa");

            if (itemsElements[0].className.indexOf("menu-items-visible") >= 0) {
                itemsElements[0].className = " menu-items menu-items-oculto";
                hamburgerElements[0].innerHTML = "☰";
            } else {
                itemsElements[0].className = "menu-items menu-items-visible";
                hamburgerElements[0].innerHTML = "Cerrar";
            }
        }

Ejercicios

Ejercicio 1

Crea una página HTML con lo siguiente:

  • 1 div cuadrado azul de tamaño 200px
  • 1 div cuadrado verde de tamaño 200px
  • 1 div cuadrado azul de tamaño 400px
  • 1 div cuadrado verde de tamaño 400px
  • Dentro cada cuadrado azul , añade otro div de color rojo con tamaño 20%
  • Dentro cada cuadrado verde , añade otro div de color rojo con tamaño 20vw

Ahora:

  • Explica la diferencia de tamaños entre los de 20% y 20vw
  • Ahora cambia el tamaño de la página y mira como de modifica el tamaño de los cuadrados. Indica cuales han cambiado de tamaño y explica porqué han cambiado de tamaño

Ejercicio 2

Crea una página HTML con lo siguiente:

  • 3 divs cuadrados de 200 pixeles de lado cada uno, de colores
    • Rojo
    • Verde
    • Azul (Que tenga Tamaño de fuente 20px)

De forma que:

  • Que el cuadrado Rojo se indique su tamaño usando px
  • Que el cuadrado Verde se indique su tamaño usando rem
  • Que el cuadrado Azul se indique su tamaño usando em

Añade ahora el siguiente CSS:

html {
  font-size:24px;
}

Y comprueba que solo se ha modificado el tamaño del cuadrado Verde.

Ejercicio 3

Crea una página HTML con lo siguiente:

  • Un div cuadrado de color rojo de forma que como mínimo tenga 100px pero a medida que el ancho de la pantalla se hace mas grande , se hagan también mas grande el cuadrado.
  • Un div cuadrado de color verde de forma que como máximo tenga 800px pero a medida que el ancho de la pantalla se hace mas pequeña, se hagan también mas pequeño el cuadrado.
  • Un div cuadrado de color azul de forma que como máximo tenga 800px, de tamaño mínimo tenga 100px, pero a medida que el ancho de la pantalla se hace mas pequeña, se hagan también mas pequeño el cuadrado y si se hace mas grande el ancho de la pantalla, también se haga mas grande el cuadrado.
  • Un div cuadrado de color rosa de forma que su tamaño siempre sea la mitad de la pantalla mas 20px
  • Un div cuadrado de color amarillo de forma que su tamaño siempre sea la mitad de la pantalla mas 20px pero no pueda ser menor que 100px ni mayor que 600px

Ejercicio 4

Haz una página HTML de forma que se cargue una imagen distinta según el siguiente ancho de la pantalla:

  • menos de 500px
  • entre 500px y 1000px
  • mas de 1000px

Ejercicio 5

Dado el típico layout de cabecera, menú lateral, cuerpo y pie. Haz una página HTML pero de forma que si el tamaño de la pantalla es menor que 500px no se vea el menú lateral.

Ejercicio 6

Crea una clase css llamada .color-fondo-responsivo de forma que cambia el color de fondo si el ancho del dispositivo (o ventana) tiene:

  • Menos de 576px sea de color rojo
  • Entre 576px y 768px sea de color verde
  • Entre 768px y 992px sea de color azul
  • Más de 992px sea de color naranja

Lo usarán en una página HTML donde estará un cuadrado de 200px x 200px

Ejercicio 7

Modifica la página del ejercicio 1 del tema anterior para hacerla responsiva:

  • Que el tamaño de los títulos, los padding y los margins cambien según la resolución.
  • Que el menú sea responsivo: cuando la pantalla es pequeña, se muestra la "hamburguesa".
  • Añade alguna imagen al cuerpo y que se oculte en tamaños pequeños.
clase/daw/diw/css-responsivo.1792788945.txt.gz · Última modificación: por claude