Giter Site home page Giter Site logo

googlechromelabs / layout-shift-terminator Goto Github PK

View Code? Open in Web Editor NEW
35.0 4.0 4.0 224 KB

Home Page: https://googlechromelabs.github.io/layout-shift-terminator/

License: Apache License 2.0

JavaScript 43.85% HTML 51.52% CSS 4.42% Shell 0.20%
cwv cls px

layout-shift-terminator's Introduction

Layout Shift Terminator

This tool aims to reduce cumulative layout shift (CLS) for markup that lacks intrinsic sizing (and thus has visual instability). This issue is most often seen with social media embeds. In contrast with an image, iframe, or video which can (and should) be added with width and height attributes that correspond to the actual width and height of the content, this is often impossible for social media embeds with textual content that will have a variable height, especially considering the various screen sizes of the devices viewing the content.

Given a series of viewport dimensions for popular device form factors (e.g. mobile, tablet, desktop), this tool loads the markup into an iframe sized for each viewport. It waits for the page to load and then measures the size of the rendered markup for each viewport. Once these viewport-specific markup measurements are obtained, it then generates CSS container queries with the appropriate min-height for each viewport width. The original markup is wrapped with a div which includes this CSS as an inline style along with a script that will remove the style after a 4-second delay. This 4-second delay is intended to give the markup time to load before removing the min-height styles, which would not be needed anymore once the embed is loaded.

In short, this tool seeks to automate the process outlined for Embeds and iframes in Optimize Cumulative Layout Shift. It aims to improve Core Web Vitals (CWV) and thus enhance page experience.

In the end, a page which optimizes layout-unstable markup using this tool should have much less cumulative layout shift. This will make the page more likely to have a good page experience.

layout-shift-terminator's People

Contributors

dependabot[bot] avatar westonruter avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

layout-shift-terminator's Issues

Add CLS calculation

When the markup is provided to obtain the dimensions, and the markup is rendered into the various viewports, the layout shift should be captured at each viewport and then summarized once the calculation has completed. Then when loading up the optimized markup in the preview, the calculation should be performed again. This can then be used to show how much layout shift savings is gained.

Integrate with WordPress block editor via plugin

When someone adds an embed block to a post, automatically calculate the media/container queries in the background and include the results as block attributes. Then wrap the embed with the layout shift termination markup when it is served.

Add UI for user to input the media queries for their main content width

Given that the viewport width is often not the same content width (given sidebars, margins, etc), the calculated heights for the embeds may not be accurate for the media queries. While the generated output includes container queries, those aren't supported by any stable browser yet. Therefore, to ensure that the computed media queries are accurate there needs to be a way for the user to indicate the widths of the main content area (in which the embed will appear) at the various viewport sizes. Ideally this could be done automatically when the tool is used in the context of a site (e.g. as a WordPress plugin).

Combine duplicate media queries

Given this example input:

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Native &lt;img&gt; lazy-loading is coming to the web! <a href="https://t.co/LgF7F1iMgR">https://t.co/LgF7F1iMgR</a> &lt;img loading=lazy&gt; defers offscreen images until the user scrolls near them. Shipping in Chrome ~75 <a href="https://t.co/4gR7lvx4zx">https://t.co/4gR7lvx4zx</a> <a href="https://t.co/luCHEfLkKD">pic.twitter.com/luCHEfLkKD</a></p>— Addy Osmani (@addyosmani) <a href="https://twitter.com/addyosmani/status/1114777583302799360?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

The output is:

<div id="layout-shift-termination-0-24900068026844013">
<style class='layout-shift-termination'>
#layout-shift-termination-0-24900068026844013 { contain: style layout inline-size; }
#layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:606px; }
@media only screen and ( max-width: 1536px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:606px; } }
@media only screen and ( max-width: 1366px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:606px; } }
@media only screen and ( max-width: 768px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:606px; } }
@media only screen and ( max-width: 700px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:606px; } }
@media only screen and ( max-width: 600px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:606px; } }
@media only screen and ( max-width: 500px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:568px; } }
@media only screen and ( max-width: 414px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:543px; } }
@media only screen and ( max-width: 375px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:466px; } }
@media only screen and ( max-width: 360px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:457px; } }
@container ( max-width: 1536px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:606px; } }
@container ( max-width: 1366px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:606px; } }
@container ( max-width: 768px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:606px; } }
@container ( max-width: 700px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:606px; } }
@container ( max-width: 600px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:606px; } }
@container ( max-width: 500px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:568px; } }
@container ( max-width: 414px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:543px; } }
@container ( max-width: 375px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:466px; } }
@container ( max-width: 360px ) { #layout-shift-termination-0-24900068026844013 > .layout-shift-terminated { min-height:457px; } }
</style>
<script class='layout-shift-termination' async>(function (root) {
    setTimeout(function () {
      [].map.call(root.querySelectorAll(".layout-shift-termination"), (el) =>
        el.remove()
      );
    }, 4000);
  })(document.getElementById("layout-shift-termination-0-24900068026844013"))</script>
<div class="layout-shift-terminated">
              <blockquote class="twitter-tweet"><p lang="en" dir="ltr">Native &lt;img&gt; lazy-loading is coming to the web! <a href="https://t.co/LgF7F1iMgR">https://t.co/LgF7F1iMgR</a> &lt;img loading=lazy&gt; defers offscreen images until the user scrolls near them. Shipping in Chrome ~75 <a href="https://t.co/4gR7lvx4zx">https://t.co/4gR7lvx4zx</a> <a href="https://t.co/luCHEfLkKD">pic.twitter.com/luCHEfLkKD</a></p>— Addy Osmani (@addyosmani) <a href="https://twitter.com/addyosmani/status/1114777583302799360?ref_src=twsrc%5Etfw">April 7, 2019</a></blockquote>
              <script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
            </div>
</div>

Note how the first 5 media queries all have the same min-height:606px; These can either be eliminated entirely because the initial min-height is 606px, or else they can be merged into one media query.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.