.htaccess file for react app – How to deploy react app to apache server with direct link access?

.htaccess settings for react application!

when you refresh your react js app you will see 404 not found page in your server. because when you click a link react router makes connection with pages but if you open link directly in the new tab you will see 404 because this url doesnt belong to react app. So react app doesnt have controll over this page. To handle this link with react router we need to rewrite url with this htaccess file.

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

Also if you want browser cache for all css, js and image files you can use also this htaccess example it will boost your page speed :

https://gokhancelebi.net/htaccess-browser-cache-example-for-all-files-images-js-css/

For browser cache use this .htaccess file

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]


<IfModule mod_deflate.c>
# Insert filters / compress text, html, javascript, css, xml:
# mod_deflate can be used for Apache v2 and later and is the recommended GZip mechanism to use
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/vtt 
AddOutputFilterByType DEFLATE text/x-component
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/js
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-httpd-fastphp
AddOutputFilterByType DEFLATE application/atom+xml 
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE application/ld+json 
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject 
AddOutputFilterByType DEFLATE application/x-font-ttf 
AddOutputFilterByType DEFLATE application/font-sfnt
AddOutputFilterByType DEFLATE application/x-web-app-manifest+json 
AddOutputFilterByType DEFLATE font/opentype 
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE font/sfnt
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon 

# Exception: Images
SetEnvIfNoCase REQUEST_URI \.(?:gif|jpg|jpeg|png)$ no-gzip dont-vary

# Drop problematic browsers
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

# Make sure proxies don't deliver the wrong content
<IfModule mod_headers.c>
Header append Vary User-Agent env=!dont-vary
</IfModule>

</IfModule>

# mod_gzip is an external extension and last updated 2015, so
# if available please use mod_deflate instead
# If you are stuck on Apache v1.3 you can use mod_zip to enable Gzip
# as mod_deflate is available for Apache v2 or later only.
<IfModule mod_gzip.c>
  mod_gzip_on Yes
  mod_gzip_dechunk Yes
  mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
  mod_gzip_item_include handler ^cgi-script$
  mod_gzip_item_include mime ^text/.*
  mod_gzip_item_include mime ^application/x-javascript.*
  mod_gzip_item_exclude mime ^image/.*
  mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</IfModule>


## EXPIRES CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 week"

ExpiresByType text/css "access plus 1 month"

ExpiresByType application/atom+xml "access plus 1 hour" 
ExpiresByType application/rdf+xml "access plus 1 hour"
ExpiresByType application/rss+xml "access plus 1 hour" 

ExpiresByType application/json "access plus 0 seconds"
ExpiresByType application/ld+json "access plus 0 seconds"
ExpiresByType application/schema+json "access plus 0 seconds"
ExpiresByType application/vnd.geo+json "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType text/xml "access plus 0 seconds" 

ExpiresByType image/x-icon "access plus 1 month"
ExpiresByType image/vnd.microsoft.icon "access plus 1 month"

ExpiresByType text/html "access plus 1 minute"

ExpiresByType text/javascript "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 months"
ExpiresByType application/x-javascript "access plus 1 months"

ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month" 
ExpiresByType image/bmp "access plus 1 month"
ExpiresByType image/webp "access plus 1 month"

ExpiresByType audio/ogg "access plus 1 month" 

ExpiresByType video/mp4 "access plus 1 month" 
ExpiresByType video/ogg "access plus 1 month" 
ExpiresByType video/webm "access plus 1 month" 

ExpiresByType text/plain "access plus 1 month"
ExpiresByType text/x-component "access plus 1 month" 

ExpiresByType application/manifest+json "access plus 1 week"
ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
ExpiresByType text/cache-manifest "access plus 0 seconds"

ExpiresByType application/pdf "access plus 1 month"

ExpiresByType application/x-shockwave-flash "access plus 1 month"

ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
ExpiresByType font/eot "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month" 
ExpiresByType application/x-font-ttf "access plus 1 month" 
ExpiresByType application/font-woff "access plus 1 month" 
ExpiresByType application/font-woff2 "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 month"
ExpiresByType font/woff "access plus 1 month"

</IfModule>
## EXPIRES CACHING ##


#Alternative caching using Apache's "mod_headers", if it's installed.
#Caching of common files - ENABLED
<IfModule mod_headers.c>

# 1 Month
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=2592000, public"
</FilesMatch>

# 2 DAYS
<FilesMatch "\.(xml|txt)$">
Header set Cache-Control "max-age=172800, public, must-revalidate"
</FilesMatch>

# 2 HOURS
<FilesMatch "\.(html|htm)$">
Header set Cache-Control "max-age=7200, must-revalidate"
</FilesMatch>

</IfModule>


<IfModule mod_headers.c>
  <FilesMatch "\.(js|css|xml|gz|html|ttf)$">
    Header append Vary: Accept-Encoding
  </FilesMatch>
</IfModule>

# Set Keep Alive Header
# This *just* sets the header - maybe your hoster is not allowing this feature
# Please check if it is working with tools like http://www.webpagetest.org
<IfModule mod_headers.c>
    Header set Connection keep-alive
</IfModule>

# If your server don't support ETags deactivate with "None" (and remove header)
<IfModule mod_expires.c> 
  <IfModule mod_headers.c> 
    Header unset ETag 
  </IfModule> 
  FileETag None 
</IfModule>

.htaccess browser cache example for all files images, js , css

With this htaccess file you will store all of your assets in user’s browser for a month.

images, js files, css files, icons, font files,svg files and other file types.

<IfModule mod_deflate.c>
# Insert filters / compress text, html, javascript, css, xml:
# mod_deflate can be used for Apache v2 and later and is the recommended GZip mechanism to use
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/vtt 
AddOutputFilterByType DEFLATE text/x-component
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/js
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-httpd-fastphp
AddOutputFilterByType DEFLATE application/atom+xml 
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE application/ld+json 
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject 
AddOutputFilterByType DEFLATE application/x-font-ttf 
AddOutputFilterByType DEFLATE application/font-sfnt
AddOutputFilterByType DEFLATE application/x-web-app-manifest+json 
AddOutputFilterByType DEFLATE font/opentype 
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE font/sfnt
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon 

# Exception: Images
SetEnvIfNoCase REQUEST_URI \.(?:gif|jpg|jpeg|png)$ no-gzip dont-vary

# Drop problematic browsers
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

# Make sure proxies don't deliver the wrong content
<IfModule mod_headers.c>
Header append Vary User-Agent env=!dont-vary
</IfModule>

</IfModule>

# mod_gzip is an external extension and last updated 2015, so
# if available please use mod_deflate instead
# If you are stuck on Apache v1.3 you can use mod_zip to enable Gzip
# as mod_deflate is available for Apache v2 or later only.
<IfModule mod_gzip.c>
  mod_gzip_on Yes
  mod_gzip_dechunk Yes
  mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
  mod_gzip_item_include handler ^cgi-script$
  mod_gzip_item_include mime ^text/.*
  mod_gzip_item_include mime ^application/x-javascript.*
  mod_gzip_item_exclude mime ^image/.*
  mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</IfModule>


## EXPIRES CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 week"

ExpiresByType text/css "access plus 1 month"

ExpiresByType application/atom+xml "access plus 1 hour" 
ExpiresByType application/rdf+xml "access plus 1 hour"
ExpiresByType application/rss+xml "access plus 1 hour" 

ExpiresByType application/json "access plus 0 seconds"
ExpiresByType application/ld+json "access plus 0 seconds"
ExpiresByType application/schema+json "access plus 0 seconds"
ExpiresByType application/vnd.geo+json "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType text/xml "access plus 0 seconds" 

ExpiresByType image/x-icon "access plus 1 month"
ExpiresByType image/vnd.microsoft.icon "access plus 1 month"

ExpiresByType text/html "access plus 1 minute"

ExpiresByType text/javascript "access plus 1 month"
ExpiresByType text/x-javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 months"
ExpiresByType application/x-javascript "access plus 1 months"

ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month" 
ExpiresByType image/bmp "access plus 1 month"
ExpiresByType image/webp "access plus 1 month"

ExpiresByType audio/ogg "access plus 1 month" 

ExpiresByType video/mp4 "access plus 1 month" 
ExpiresByType video/ogg "access plus 1 month" 
ExpiresByType video/webm "access plus 1 month" 

ExpiresByType text/plain "access plus 1 month"
ExpiresByType text/x-component "access plus 1 month" 

ExpiresByType application/manifest+json "access plus 1 week"
ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
ExpiresByType text/cache-manifest "access plus 0 seconds"

ExpiresByType application/pdf "access plus 1 month"

ExpiresByType application/x-shockwave-flash "access plus 1 month"

ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
ExpiresByType font/eot "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month" 
ExpiresByType application/x-font-ttf "access plus 1 month" 
ExpiresByType application/font-woff "access plus 1 month" 
ExpiresByType application/font-woff2 "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 month"
ExpiresByType font/woff "access plus 1 month"

</IfModule>
## EXPIRES CACHING ##


#Alternative caching using Apache's "mod_headers", if it's installed.
#Caching of common files - ENABLED
<IfModule mod_headers.c>

# 1 Month
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=2592000, public"
</FilesMatch>

# 2 DAYS
<FilesMatch "\.(xml|txt)$">
Header set Cache-Control "max-age=172800, public, must-revalidate"
</FilesMatch>

# 2 HOURS
<FilesMatch "\.(html|htm)$">
Header set Cache-Control "max-age=7200, must-revalidate"
</FilesMatch>

</IfModule>


<IfModule mod_headers.c>
  <FilesMatch "\.(js|css|xml|gz|html|ttf)$">
    Header append Vary: Accept-Encoding
  </FilesMatch>
</IfModule>

# Set Keep Alive Header
# This *just* sets the header - maybe your hoster is not allowing this feature
# Please check if it is working with tools like http://www.webpagetest.org
<IfModule mod_headers.c>
    Header set Connection keep-alive
</IfModule>

# If your server don't support ETags deactivate with "None" (and remove header)
<IfModule mod_expires.c> 
  <IfModule mod_headers.c> 
    Header unset ETag 
  </IfModule> 
  FileETag None 
</IfModule>

JQuery on click for dynamically added elements – why it is not working?

Hi, in this writing i will be explaining you how to attach on click event for the dynamically created element to the html page.

Why i cant add on click event to the dynamically added element like static elements?

Because when you run javascript code in the page starts, jquery tries to find element you add event to it. But it cant find element because you will create element dynamically so you need to reconnect your element wity your function.

In this code below you make a click event listener to all of your page and when this event trigers it uses some kind of filter for the selector (id , class , element name) you passed as second paramater. And then it runs the function that you passed as third argument to this jquery event function.

In the end of the day you catch all click elements but runs just for your filtered element(s).

$(document).on('click','#element',function(){
    alert('Clicked')
 });

Full Example

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Element Visibility</title>
</head>

<body>
    
    <script>
        $(function () {
            // add element to the page dynamically
            $('body').append('<button id="element">Button</button>');

            // add on click listener for element
            $(document).on('click','#element',function(){
                alert('Clicked')
            });
        });
    </script>
</body>

</html>

How to detect when element is visible on screen with Javascript

When user comes to the page you may want to show them animation and if element is in the bottom of page, you need to wait untill element is visible on screen to run your animation. With this ready to use function you can add this functionality all elements on screen. Also i have a youtube video that explains how i wrote this function.

Ready to use full JS code

function gc_detect_visibility(query,custom_funtion){

    let calculator = function(query,custom_funtion){
        
        let element = document.querySelector(query);

        let element_top_offset = element.offsetTop;
        let element_bottom_offset = element.offsetHeight + element_top_offset;

        let screen_top_offset = window.scrollY;
        let screen_bottom_offset = screen_top_offset + window.innerHeight;

        if(element_top_offset > screen_top_offset && screen_bottom_offset > element_bottom_offset){
            custom_funtion(element);
        }
    } 

    calculator(query,custom_funtion);

    document.addEventListener('scroll',calculator.bind(null,query,custom_funtion));
}

Example usage

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Detect Visibility</title>
</head>

<body>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box" id="element"></div>
    <div class="box"></div>
    <div class="box"></div>
    <style>
        .box {
            width: 250px;
            height: 250px;
            background-color: blue;
            margin-bottom: 20px;
        }

        #element {
            background-color: red;
        }
    </style>
    <script>
        function gc_detect_visibility(query,custom_funtion){

            let calculator = function(query,custom_funtion){
                
                let element = document.querySelector(query);

                let element_top_offset = element.offsetTop;
                let element_bottom_offset = element.offsetHeight + element_top_offset;

                let screen_top_offset = window.scrollY;
                let screen_bottom_offset = screen_top_offset + window.innerHeight;

                if(element_top_offset > screen_top_offset && screen_bottom_offset > element_bottom_offset){
                    custom_funtion(element);
                }
            } 

            calculator(query,custom_funtion);

            document.addEventListener('scroll',calculator.bind(null,query,custom_funtion));
        }

        gc_detect_visibility('#element',function(element){
            console.log('element is visible');
        });

    </script>

</body>

</html>

Js detect element when visible on viewport

To do that as you can see in the video and the code i share with you above. We need to calculate if element is visible on screen by finding element top offset and screen top offset. If element top offset is higer than screen top offset and if element bottom offset is lower than screen bottom offset it makes element is visible on screen.

                let element_top_offset = element.offsetTop;
                let element_bottom_offset = element.offsetHeight + element_top_offset;

                let screen_top_offset = window.scrollY;
                let screen_bottom_offset = screen_top_offset + window.innerHeight;

                if(element_top_offset > screen_top_offset && screen_bottom_offset > element_bottom_offset){
                    custom_funtion(element);
                }

In the this part of the code we gave this functionality to the function.

Also we need to add this function into the scroll event also we need to add any element query selector into it. That is why we create another function for that in the fist lines of the function.

We created “calculator” function to add this functionality to scroll event. That makes our code run every scroll behavior. Also we bind our custom function to run when element is visible on screen or viewport.

With this approach you can add any functionality to your code. Change the calculation based on your situation and solve your problem with that.

Woocommerce update product attributes in php

This php function allows you to update simple product attributes in woocommerce.

<?php


function update_product_attributes($product_id, $attributes){

    $product = new WC_Product($product_id);

    $product_attributes = array();

    delete_transient('wc_attribute_taxonomies');

    foreach ($attributes as $key => $terms) {
        $taxonomy = wc_attribute_taxonomy_name($key); // The taxonomy slug
        $attr_label = ucfirst($key); // attribute label name
        $attr_name = (wc_sanitize_taxonomy_name($key)); // attribute slug


        delete_transient('wc_attribute_taxonomies');


        // NEW Attributes: Register and save them
        if (!taxonomy_exists($taxonomy))
            save_product_attribute_from_name($attr_name, $attr_label);

        delete_transient('wc_attribute_taxonomies');

        $is_variation = 0;

        if ($key == "Color") {
            $is_variation = 1;
        }

        $product_attributes[$taxonomy] = array(
            'name' => $taxonomy,
            'value' => '',
            'position' => 0,
            'is_visible' => 1,
            'is_variation' => $is_variation,
            'is_taxonomy' => 1
        );

        foreach ($terms as $value) {
            $term_name = ucfirst($value);
            $term_slug = sanitize_title($value);


            delete_transient('wc_attribute_taxonomies');


            // Check if the Term name exist and if not we create it.
            if (!term_exists($value, $taxonomy))
                wp_insert_term($term_name, $taxonomy, array('slug' => $term_slug)); // Create the term


            delete_transient('wc_attribute_taxonomies');


            // Set attribute values
            wp_set_post_terms($product_id, $term_name, $taxonomy, true);
        }
    }
    update_post_meta($product_id, '_product_attributes', $product_attributes);
    $product->save();
}

How to read and write excel files in php

How to install phpspreadsheet library with composer

composer require phpoffice/phpspreadsheet

How to Write and save excel files (CSV, XLSX, XLS) Just change Xlsx to other types if you need.

<?php

require 'vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', 'Hello World !');

$writer = new Xlsx($spreadsheet);
$writer->save('hello world.xlsx');

How to read excel files as array

<?php

require 'vendor/autoload.php';

$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();

$spreadsheet = $reader->load(__DIR__ . '/data.xlsx');
$sheetData = $spreadsheet->getActiveSheet()->toArray();

PHP wordpress upload image from URL to media library directly

      require_once(ABSPATH . 'wp-admin/includes/media.php');
        require_once(ABSPATH . 'wp-admin/includes/file.php');
        require_once(ABSPATH . 'wp-admin/includes/image.php');


        $image_id = media_sideload_image($image_url, 0, null, "id");

Second way for existing images in FTP :

<?php $file = $images_DIR . $sku . '.jpg';
        $attachment = [
            'post_mime_type' => 'image/jpeg',
            'post_title' => $sku,
            'post_content' => '',
            'post_status' => 'inherit'
        ];
        $attach_id = wp_insert_attachment($attachment, $file, $product_id);
        $attach_data = wp_generate_attachment_metadata($attach_id, $file);
        wp_update_attachment_metadata($attach_id, $attach_data);
        set_post_thumbnail($product_id, $attach_id);

PHP WordPress Delete All Posts with thumbnail image permanently

Delete all image, meta data and post permanently.


# delete all posts
$args = array(
    'post_type' => 'post',
    'posts_per_page' => -1,
    'post_status' => 'any'
);
$posts = get_posts($args);
foreach ($posts as $post) {
    # delete post thumbnail
    $thumbnail_id = get_post_thumbnail_id($post->ID);
    if ($thumbnail_id) wp_delete_attachment($thumbnail_id, true);
    wp_delete_post($post->ID, true);
}

Javascript check if element is visible on screen – check viewport

why we made in this code ? Line by line js code?

Check if element is visible in viewport using javascript library in javascript and add scroll event to detect when element is in screen:

Video and new version of this writing is here : https://gokhancelebi.net/how-to-detect-when-element-is-visible-on-screen-with-javascript/

Ready to Use FULL Code

// detect when element gets visible on scroll
    window.addEventListener("scroll", detect_visibility);

    // detect when screen opens for first time
    detect_visibility();

    function detect_visibility() {

        var element = document.getElementById("element");

        var top_of_element = element.offsetTop;
        var bottom_of_element = element.offsetTop + element.offsetHeight + element.style.marginTop;
        var bottom_of_screen = window.scrollY + window.innerHeight;
        var top_of_screen = window.scrollY;

        if ((bottom_of_screen > top_of_element) && (top_of_screen < bottom_of_element)) {
            // Element is visible write your codes here
            // You can add animation or other codes here
            alert("element is visible")
        } else {
            // the element is not visible, do something else
            alert("element is not visible")
        }

    }

detect_visibility ()

With this function i wrote you above you can detect if element inside secreen viewport. It calculates based on offset and element height. You can use this to implement lazyload or animations.

You can add animaton classes in the // Element is visible section of detect_visibility function

Element Top Offset

   var top_of_element = element.offsetTop;

In this line of code we get offset of element that we want to know if it is visibile.

Element Bottom Offset

var bottom_of_element = element.offsetTop + element.offsetHeight + element.style.marginTop;

In this line of code we get bottom offset of element

Window Bottom Offset and Top Offset

var bottom_of_screen = window.scrollY + window.innerHeight;
var top_of_screen = window.scrollY;

In the first line we get window screen’s bottom offset

In the second line we get windows screen’s top offset

Final : Calculate to detect if element is visible and shown on screen of user

if ((bottom_of_screen > top_of_element) && (top_of_screen < bottom_of_element)) {
      // Element is visible write your codes here
      // You can add animation or other codes here
      alert("element is visible")
} else {
      // the element is not visible, do something else
      alert("element is not visible")
 }