Podríamos validar esto accediendo primero a los valores de la "ventana de visualización" , para esto se hace uso de scrollTop del objeto window
para saber cuando se desplazó hacía abajo y el limite lo obtenemos de la suma del valor devuelvo por scrollTop
+ height
de la ventana
Luego tendríamos que realizar el mismo procedimiento para el elemento
, para esto emplearemos offset para las coordenadas y acceder a la propiedad top
para luego obtener la altura del elemento también con height
Ya con estos valores validaríamos comparando , la función quedaría así:
function esVisible(elem){
/* Ventana de Visualización*/
var posTopView = $(window).scrollTop();
var posButView = posTopView + $(window).height();
/* Elemento a validar*/
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
/* Comparamos los dos valores tanto del elemento como de la ventana*/
return ((elemBottom < posButView && elemBottom > posTopView) || (elemTop >posTopView && elemTop< posButView));
}
$("button").on("click", function() {
var ele = document.getElementById('holamundo');
console.log(esVisible(ele));
});
button {
position:fixed;
top:5px;
right:5px;
}
p {
margin-top: 800px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>¿Está "Hola Mundo" visible?</button>
<div id="holamundo">Hola Mundo</div>
<p>.</p>
<p>.</p>
Update
Como recomendación de @Alvaro Montoro , Con el ejemplo anterior funcionaría pero height no tomará en cuenta el padding
como sí lo hace outerheight
function esVisible(elem){
/* Ventana de Visualización*/
var posTopView = $(window).scrollTop();
var posButView = posTopView + $(window).height();
/* Elemento a validar*/
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).outerHeight();
/* Comparamos los dos valores tanto del elemento como de la ventana*/
return ((elemBottom < posButView && elemBottom > posTopView) || (elemTop >posTopView && elemTop< posButView));
}
$("button").on("click", function() {
var ele = document.getElementById('holamundo');
console.log(esVisible(ele));
});
button {
position:fixed;
top:5px;
right:5px;
}
p {
margin-top: 800px;
}
#holamundo{
padding: 120px;
background: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>¿Está "Hola Mundo" visible?</button>
<div id="holamundo">Hola Mundo</div>
<p>.</p>
<p>.</p>
Ejemplo empleando solo JavaScript
function esVisible(elem){
var posTopView = window.scrollY;
var posButView = posTopView + window.innerHeight;
var elemTop = elem.offsetTop;
var elemBottom = elemTop + elem.offsetHeight;
return ((elemBottom < posButView && elemBottom > posTopView) || (elemTop >posTopView && elemTop< posButView));
}
document.getElementById('btn').addEventListener("click", function(){
var ele = document.getElementById('holamundo');
console.log(esVisible(ele));
});
button {
position:fixed;
top:5px;
right:5px;
}
p {
margin-top: 800px;
}
<button id="btn">¿Está "Hola Mundo" visible?</button>
<div id="holamundo">Hola Mundo</div>
<p>.</p>
<p>.</p>
Referencia en SO
Update
Otra opción sería utilizar la API IntersectionObserver() para saber si el elemento está visible
o no.
Crear el objeto de opciones con tres valores root
, está propiedad determina el elemento donde se validará la visibilidad del elemento a observar,por defecto toma el viewport del navegador
rootMargin
, esta propiedad determina el margen que se incluirá en la evaluación de la visibilidad
threshold
, esta propiedad determina el porcentaje de visibilidad que se desea observar, el valor por defecto es 0 es decir que tan pronto como sea visible (1px mínimo),
y 1 cuando el elemento esté completamente visible. esta propiedad se pueden pasar más de 1 parámetro, revisar la documentación. :)
Crear la instancia de IntersectionObserver
, como primer parámetro un callback y como segundo parámetro el objeto de opciones
Asignar el observer al o los elementos a evaluar. Para el ejemplo solo uno con el id holamundo
Dentro del callback tendrá el parámetro entries que hará referencia a los elementos observados, (el ejemplo el elemento sería el indice 0), a través
de isIntersecting
verificamos si está visible teniendo en cuenta las opciones, a partir de eso podemos realizar acciones según sea el caso.
function callback(entries,observer){
if(entries[0].isIntersecting){//verificamos si actualmente es visible
console.log("El elemento ya está visible...");
}else{
console.log("El elemento no es visible.");
}
}
var observer = new IntersectionObserver(callback, {});
const element = document.querySelector('#holamundo');
observer.observe(element);
.boxMargin {
width: 300px;
height: 400px;
border : 1px solid #aec;
}
<div class="boxMargin"></div>
<div class="boxMargin"></div>
<div id="holamundo">Hola Mundo</div>
<div class="boxMargin"></div>
<div class="boxMargin"></div>