En ocasiones podemos necesitar detectar si un elemento HTML es visible en la ventana de nuestro navegador para lanzar un aviso, una alerta, etc. Es un problema muy sencillo de límites que abordaremos en este artículo.

Para ello podemos utilizar un desarrollo que calculará las dimensiones de nuestro navegador y su posición; y la posición y dimensiones del elemento en cuestión. En principio sólo tendremos en cuenta el eje vertical por lo que escucharemos los eventos de scroll y resize de la ventana para lanzar la función.

La naturaleza del problema

Este es uno de los problemas que nos encontramos con más frecuencia en programación, ya sea en frontend, consulta de BD, etc. Los problemas de límites. Para detectar si un elemento es visible en nuestra ventana del navegador deberemos de tener en cuenta los siguientes valores:

  1. Posición en la que se encuentra la parte que estamos viendo del documento HTML respecto al inicio del mismo. Para ello podemos utilizar el método de jQuery scrollTop().
    var windowTop = $(document).scrollTop();
  2. El punto más bajo que estamos viendo ahora mismo en la ventana del navegador del documento HTML. O lo que es lo mismo, la altura interna de nuestro navegador.
    var windowBottom = windowTop + window.innerHeight;
  3. La posición en la que se encuentra la parte superior del elemento que queremos observar respecto al inicio del documento. Podemos elegir cualquier elemento HTML con jQuery. Utilizaremos el valor del atributo top obtenido con el método offset() de jQuery.
    var elementPositionTop = element.offset().top;
  4. Y la última parte de nuestro problema geométrico es conocer la altura del elemento a observar que obtendremos con el método height().
    var elementPositionBottom = elementPositionTop + element.height();

Límites a tener en cuenta

Vamos a simplificar al máximo nuestra función. Por defecto vamos a asumir que el elemento es visible por defecto, así que tendremos que determinar las condiciones en las que NO será visible en la ventana de nuestro navegador.

  1. Cuando el límite superior del elemento sea mayor que la posición inferior de la ventana significará que todo el documento estará por debajo de la parte visible:
    elementPositionTop > windowBottom
  2. Cuando el límite inferior del elemento sea menor que la posición superior de la ventana significará que todo el documento estará por encima de la parte visible:
    elementPositionBottom < windowTop

En cualquier otra situación nuestro elemento será visible.

var visible = true;

Revisemos el código

Como podemos ver he creado una función initShazam (es un nombre tan malo o bueno como otro cualquiera) que lo único que hace es cada vez que hagamos scroll o modifiquemos la ventana del navegador realiza una inscripción true o false en la consola JavaScript según sea visible o no nuestro elemento.

A partir de aquí tenemos una función que nos puede permitir realizar cualquier acción cuando se muestre en ventana un elemento HTML: iniciar una animación, mostrar otros elementos HTML, lanzar una petición AJAX, etc. Espero os sea de utilidad en vuestros propios desarrollos.

 
  Shazam
 
<style>
  div{
    height: 1200px;
    background-color: maroon;
    border: 5px solid red;
    width: 75%;
    margin: 0 auto;
    margin-top: 800px;
  }
  body {
    height: 2000px;
  }
  </style>
Elemento de prueba


Comparte si te ha gustado

Autor:
Última actualización:

8 comentarios

  1. Hola, esto es precisamente lo que estaba buscando, para aplicar unas clases de uikit cuando los elementos vayan siendo visibles.

    Mi problema es que no se donde meter los addClass(). He intentado preguntar if (visible==true) en un par de sitios y tal, pero no he dado con la tecla.

    Un saludo y gracias!

  2. Debes de elegir los elementos que quieras detectar si son visibles o no. Te pongo un ejemplo que utilizo en la Home del blog, para que cuando sean visibles unos iconos realicen un fadeIn(), pero puedes sustituir el método por un addClass().


    function initShazam(elementShazam) {
      var icons = 'div.logos .icon-stack';
      $(icons).hide();
      $(window).on('scroll resize', function () {
        if (elementVisible(elementShazam) && !elementShazam.hasClass('shazam')) {
          $(icons + '.logo2,' + icons + '.logo4').delay(500).fadeIn(1000);
          $(icons + '.logo1,' + icons + '.logo3,' + icons + '.logo5').delay(1500).fadeIn(1000);
          $(icons + '.logo6,' + icons + '.logo7').delay(2500).fadeIn(1000);
          elementShazam.addClass('shazam');
        }
      });
    }

  3. Muchas gracias, me has ayudado mucho, soy novato y te agradecería mucho que me ayudaras y me indicaras como hago para que tome el div por medio de un selector de clase o un id y no con el selector de etiqueta “div” … de nuevo muchas gracias y buen día (y)

  4. Gracias por el aporte! Pero hay un pequeño fallo que me estaba dando problemas con esta solución. Pongo la corrección:
    function elementVisible(element) {
    var visible = true;
    var windowTop = $(document).scrollTop();
    var windowBottom = windowTop + window.innerHeight;
    var elementPositionTop = element.offset().top;
    var elementPositionBottom = elementPositionTop + element.height();
    if (elementPositionTop >= windowBottom || elementPositionBottom <= windowTop) {
    visible = false;
    }
    return visible;
    }

    = si no lo añadimos si el elemento esta fuera de la pantalla por 1px seguirá diciendo que es visible 🙂

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.