Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                .section
  h1 Welcome 👋
.section.animated-btn-container
  .section__inner.container
    .section__header
      h3
        span Step 3:
        span Lorem ipsum
        span dolor sit amet
      p Lorem ipsum, dolor sit amet consectetur adipisicing elit.
    .section__body
      img(src="https://i.ibb.co/zP7MgBC/dummy-phone.png" alt="Dummy Photo")
  a.external-link(href="https://www.apple.com/app-store/" target="_blank")
    .external-link__icon
      img(src="https://dummyimage.com/78x78/b2b2b2/fff" alt="Lorem ipsum")
    .external-link__label Download
    
.section.extra
              
            
!

CSS

              
                @import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,500;0,700;1,400&display=swap");

// ===================================================================
// Flexbox Grid Mixins
// Version 0.2.1
// Description: Sass Mixins to generate Flexbox grid
// Author: thingsym
// GitHub: https://github.com/thingsym/flexbox-grid-mixins
// MIT License
// ===================================================================

@charset 'utf-8';

$flexbox-grid-mixins-grid-type: skeleton !default;
$flexbox-grid-mixins-box-sizing: border-box !default;
$flexbox-grid-mixins-stack: margin-bottom !default;

@mixin grid(
  $display: flex,
  $flex-direction: null,
  $flex-wrap: null,
  $flex-flow: null,
  $justify-content: null,
  $align-items: null,
  $align-content: null,
  $gutter: null
) {
  @if $flexbox-grid-mixins-box-sizing ==
    "border-box" or
    $flexbox-grid-mixins-box-sizing ==
    "content-box"
  {
    box-sizing: $flexbox-grid-mixins-box-sizing;
  }

  @if $display {
    display: $display;
  }

  @if $flex-direction {
    flex-direction: $flex-direction;
  }
  @if $flex-wrap {
    flex-wrap: $flex-wrap;
  }

  @if $flex-flow {
    flex-flow: $flex-flow;
  }

  @if $justify-content {
    justify-content: $justify-content;
  }
  @if $align-items {
    align-items: $align-items;
  }
  @if $align-content {
    align-content: $align-content;
  }

  @if $flexbox-grid-mixins-grid-type == skeleton {
    @if $gutter {
      margin-left: $gutter / 2 * -1;
      margin-right: $gutter / 2 * -1;
    }
  }

  @content;
}

@mixin grid-col(
  $col: null,
  $grid-columns: 12,
  $col-offset: null,
  $gutter: null,
  $align-self: null,
  $flex-grow: 0,
  $flex-shrink: 1,
  $flex-basis: auto,
  $order: null,
  $shorthand: true,
  $last-child: false,
  $width: null,
  $max-width: null,
  $min-width: null,
  $height: null,
  $max-height: null,
  $min-height: null
) {
  @if $flexbox-grid-mixins-box-sizing ==
    "border-box" or
    $flexbox-grid-mixins-box-sizing ==
    "content-box"
  {
    box-sizing: $flexbox-grid-mixins-box-sizing;
  }

  @if type-of($col) == number and unitless($col) == true {
    $flex-shrink: 0;
    $flex-basis: percentage($col / $grid-columns);

    @if $flexbox-grid-mixins-grid-type == skeleton {
      @if $gutter and unit($gutter) == "%" {
        $flex-basis: $flex-basis - $gutter;
      } @else if $gutter and unitless($gutter) == false {
        $flex-basis: calc(#{$flex-basis} - #{$gutter});
      }
    } @else if $flexbox-grid-mixins-grid-type == margin-offset {
      @if $gutter and unit($gutter) == "%" {
        $flex-basis: (100% - ($gutter * ($grid-columns / $col - 1))) /
          ($grid-columns / $col);
      } @else if $gutter and unitless($gutter) == false {
        $flex-basis: calc(
          #{$flex-basis} -
            #{$gutter *
            ($grid-columns / $col - 1) /
            ($grid-columns / $col)}
        );
      }
    }

    @if $col-offset and unit($col-offset) == "%" {
      $flex-basis: $flex-basis + $col-offset;
    } @else if $col-offset and unitless($col-offset) == false {
      $flex-basis: calc(#{$flex-basis} + #{$col-offset});
    }
  } @else if type-of($col) == number and unitless($col) == false {
    $flex-grow: 0;
    $flex-shrink: 0;
    $flex-basis: $col;
  } @else if type-of($col) == string and $col == "auto" {
    // flex: auto;
    $flex-grow: 1;
    $flex-shrink: 1;
    $flex-basis: auto;
  } @else if type-of($col) == string and $col == "equal" {
    // flex: 1;
    $flex-grow: 1;
    $flex-shrink: 1;
    $flex-basis: 0;
  } @else if type-of($col) == string and $col == "none" {
    // flex: none;
    $flex-grow: 0;
    $flex-shrink: 0;
    $flex-basis: auto;
  } @else if type-of($col) == string and $col == "initial" {
    // flex: initial;
    $flex-grow: 0;
    $flex-shrink: 1;
    $flex-basis: auto;
  } @else if type-of($col) == string and $col == "positive" {
    // positive number
    @if $flex-grow == 0 {
      $flex-grow: 1;
    }
    $flex-shrink: 0;
    $flex-basis: 0;
  }

  @if type-of($shorthand) == bool and $shorthand == true {
    flex: $flex-grow $flex-shrink $flex-basis;
  } @else {
    flex-basis: $flex-basis;
    flex-grow: $flex-grow;
    flex-shrink: $flex-shrink;
  }

  @if $align-self != null {
    align-self: $align-self;
  }

  @if type-of($order) == number {
    order: $order;
  }

  @if type-of($width) == bool and $width == true {
    width: $flex-basis;
  } @else if type-of($width) == number and unitless($width) == false {
    width: $width;
  } @else if type-of($width) == string and $width == "auto" {
    width: auto;
  }

  @if type-of($max-width) == bool and $max-width == true {
    max-width: $flex-basis;
  } @else if type-of($max-width) == number and unitless($max-width) == false {
    max-width: $max-width;
  } @else if type-of($max-width) == string and $max-width == "auto" {
    max-width: auto;
  }

  @if type-of($min-width) == bool and $min-width == true {
    min-width: $flex-basis;
  } @else if type-of($min-width) == number and unitless($min-width) == false {
    min-width: $min-width;
  } @else if type-of($min-width) == string and $min-width == "auto" {
    min-width: auto;
  }

  @if $height != null {
    height: $height;
  }
  @if $max-height != null {
    max-height: $max-height;
  }
  @if $min-height != null {
    min-height: $min-height;
  }

  @if $gutter and unitless($gutter) == false {
    @if $flexbox-grid-mixins-grid-type == skeleton {
      margin-left: $gutter / 2;
      margin-right: $gutter / 2;
    } @else if $flexbox-grid-mixins-grid-type == margin-offset {
      @if type-of($last-child) == bool and $last-child == true {
        margin-right: 0;
      } @else {
        margin-right: $gutter;
      }
    }

    @if $flexbox-grid-mixins-stack == margin-top {
      margin-top: $gutter;
    } @else if $flexbox-grid-mixins-stack == margin-bottom {
      margin-bottom: $gutter;
    } @else if $flexbox-grid-mixins-stack == margin-both {
      margin-top: $gutter / 2;
      margin-bottom: $gutter / 2;
    }
  }

  @content;
}

// Media breakpoints config
$breakpoints: (
  "phone-small": 321px,
  "phone": 400px,
  "phone-md": 430px,
  "phone-wide": 480px,
  "ptablet": 576px,
  "tablet-small": 640px,
  "tablet-md": 768px,
  "tablet-x": 992px,
  "tablet": 1025px,
  "tablet-large": 1141px,
  "desktop": 1280px,
  "desktop-x": 1400px
);

@mixin media($width, $type: max) {
  @if map_has_key($breakpoints, $width) {
    $width: map_get($breakpoints, $width);

    @if $type==max {
      $width: $width - 1px;
    }

    @media only screen and (#{$type}-width: $width) {
      @content;
    }
  }
}

:root {
  --color-white: #ffffff;
  --color-white-md: #f9f9f9;
  --color-black: #000000;
  --color-black-04: rgba(0, 0, 0, 0.04);
  --color-black-40: rgba(0, 0, 0, 0.4);
  --color-black-64: rgba(0, 0, 0, 0.64);
  --color-primary: rgb(31, 31, 41);
  --color-opac-p-0: rgba(31, 31, 41, 0.1);
  --color-opac-p-1: rgba(31, 31, 41, 0.4);
  --color-opac-p-2: rgba(31, 31, 41, 0.48);
  --color-opac-p-3: rgba(31, 31, 41, 0.8);
  --color-opac-p-4: rgba(31, 31, 41, 0.08);
  --color-error: #aa003e;
  --color-border-accordion: rgba(51, 51, 67);
  --color-border-bottom-accordion: rgba(51, 51, 67, 0.12);
  --color-red: #ff4d00;
  --color-yellow: #ffce7b;
  --color-green: #7fd5a2;
  --color-blue: #91cbf0;
  --font-size-1: 12px;
  --font-size-2: 16px;
  --font-size-3: 18px;
  --font-size-4: 20px;
  --font-size-5: 22px;
  --font-size-6: 24px;
  --font-size-7: 27px;
  --font-size-8: 28px;
  --font-size-9: 30px;
  --font-size-10: 38px;
  --font-size-11: 42px;
  --font-size-12: 52px;
  --container-padding-desktop: 144px;
  --container-padding-tablet: 44px;
  --container-padding-mobile: 24px;
  --container-max-width: 1152px;
  --box-size: 60px;
}

body {
  width: 100vw;
  font-family: "Roboto", sans-serif;
}

.container {
  max-width: 100%;
  margin: 0px auto;
  padding: 0px var(--container-padding-mobile);

  @include media("tablet-md", min) {
    max-width: 100%;
    margin: 0px auto;
    padding: 0px var(--container-padding-tablet);
  }

  @include media("desktop", min) {
    max-width: var(--container-max-width);
    margin: 0px auto;
    padding: 0px;
  }
}

.section {
  height: 100vh;
  position: relative;
  background-color: var(--color-white);
  padding: 40px 0px 62px 0px;
  @include grid($justify-content: center, $align-items: center);
 
  @include media("tablet-md", min) {
    padding: 65px 0px 62px 0px;
  }

  @include media("desktop", min) {
    padding: 95px 0px 110px 0px;
  }
  &:first-child {
    background-color: var(--color-white-md);
    display: flex;
    align-items: center;
    justify-content: center;
  }

  &__inner {
    display: grid;
    grid-template-areas:
      "header"
      "body";
    row-gap: 40px;

    @include media("tablet-md", min) {
      grid-template-areas:
        "header"
        "body";
      row-gap: 135px;
    }

    @include media("desktop", min) {
      grid-template-columns: 1fr 1fr;
      grid-template-areas:
        "header body"
        "header body"
        "header body";
      gap: 0px 44px;
    }
  }

  &__header {
    grid-area: header;
    h3 {
      @include grid($flex-direction: column);
      margin-bottom: 16px;

      span {
        font-family: "Roboto", sans-serif;
        font-size: var(--font-size-6);
        font-weight: 800;
        font-stretch: normal;
        font-style: normal;
        line-height: 1.25;
        letter-spacing: normal;
        color: var(--color-primary);

        &:first-child {
          color: var(--color-opac-p-1);
          @include media("tablet-md", min) {
            margin-bottom: 8px;
          }
        }

        @include media("tablet-md", min) {
          font-size: var(--font-size-9);
          line-height: 1.13;
        }

        @include media("desktop", min) {
          font-size: var(--font-size-11);
          line-height: 1.19;
        }
      }

      @include media("tablet-md", min) {
        margin-bottom: 24px;
      }

      @include media("desktop", min) {
        margin-bottom: 22px;
      }
    }

    p {
      font-family: SFProDisplay;
      font-size: var(--font-size-2);
      font-weight: normal;
      font-stretch: normal;
      font-style: normal;
      line-height: 1.38;
      letter-spacing: normal;
      color: var(--color-primary);
      margin-bottom: 0px;

      @include media("tablet-md", min) {
        font-size: var(--font-size-3);
        line-height: 1.33;
      }
    }
  }

  &__body {
    grid-area: body;

    @include media("tablet-md", min) {
      margin-top: -30px;
    }

    img {
      height: 465px;
      width: 100%;
      object-fit: cover;

      @include media("tablet-md", min) {
        height: 570px;
        object-fit: contain;
      }

      @include media("tablet-md", min) {
        max-height: 560px;
        object-fit: contain;
      }
    }
  }
}

/*
  animated button
*/
.external-link {
  width: 102px;
  height: 140px;
  padding: 8px;
  border-radius: 8px;
  box-shadow: 0 10px 10px 0 rgba(0, 0, 0, 0.3);
  background-color: var(--color-white);
  position: absolute;
  left: 32px;
  
  top: -180px;

  @include media("desktop") {
    display: none;
  }

  &__icon {
    width: 86px;
    height: 86px;
    margin: 0px auto 5px auto;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  img {
    max-width: 78px;
    object-fit: contain;
  }

  &__label {
    font-family: "Roboto", sans-serif;
    font-size: 14px;
    font-weight: bold;
    font-stretch: normal;
    font-style: normal;
    line-height: 1.14;
    letter-spacing: normal;
    text-align: center;
    color: var(--color-primary);
  }
}


body {overflow-x: hidden; margin: 0; padding: 0;}

.section.animated-btn-container{ margin-bottom :400vh; }

.section.extra{ background: lightgrey;}
              
            
!

JS

              
                gsap.registerPlugin(ScrollTrigger);

gsap.set(".external-link", { opacity: 0 });

var animatedButons = gsap.utils.toArray('.external-link');

animatedButons.forEach((button, i) => {
  
ScrollTrigger.create({    
    trigger: '.animated-btn-container',
    start: () => "top bottom",
    end: () => "+=500%",
    scrub: true,
    pin: '.external-link',
    markers: true    
})  
  
var tl = gsap.timeline({
  scrollTrigger: {
    trigger: '.animated-btn-container',
    start: () => "top bottom",
    end: () => "+=50%",
    scrub: true,
    toggleActions: "play none none reset",
    invalidateOnRefresh: true,
    markers: true,
  },
})
tl.to(button, { opacity: 1, ease: "none" });
  

  
});
              
            
!
999px

Console