This is the fourth day of my participation in the More text Challenge. For details, see more text Challenge

The above picture is from B station CodingStartup at least class text compression effect.

Implementation effect

code

Element structure

  <div class="imac">
    <h2 style="--scale: 1">Only 11.5mm. Now that's thin.</h2>
    <div class="image">
      <img src="https://www.apple.com/105/media/us/imac-24/2021/5e004d75-3ad6-4bb9-ab59-41f891fc52f0/anim/design-hero/large/flow/flow_s tartframe.jpg" alt="">
    </div>
  </div>
Copy the code

Logical structure

<script>
    let isPinned = false
    const h2 = document.querySelector('h2')
    const observer = new IntersectionObserver(([e]) = > {
      isPinned = (e.intersectionRatio < 1)
      e.target.classList.toggle('pinned', isPinned)
    }, { threshold: [1] })
    observer.observe(h2)

    document.addEventListener('scroll'.(e) = > {
      if (isPinned) {
        let html = document.documentElement
        let height = parseInt(getComputedStyle(h2).getPropertyValue('height')) + parseInt(getComputedStyle(h2).getPropertyValue('margin-bottom'))
        let marginTop = parseInt(getComputedStyle(h2).getPropertyValue('margin-top'))
        let scrolled = (html.scrollTop - marginTop) / height
        h2.style.setProperty('--scale', (1 - scrolled))
      }
    })
  </script>
Copy the code

Style structure

<style>
    body {
        margin: 0;
        padding: 0;
    }
    .image {
        position: relative;
        overflow: hidden;
    }

    .imac img {
        display: block;
        position: relative;
        top: 50%;
        left: 50%;
        transform: translate(calc(-50% - 30px), 0);
    }
    h2 {
        font-size: 72px;
        font-family: Helvetica;
        letter-spacing: -.012em;
        width: 290px;
        font-weight: normal;
        position: relative;
        left: 50%;
        position: sticky;
        top: -1px;
        margin: 100px 0;
        padding: 0;
        transform: scale(clamp(0.15.var(--scale), 1));
        transform-origin: 0% 0%;
    }

    .pinned {
    	color: red;
    }
</style>
Copy the code
  • The first kind of

    • <style>
          h2 {
            transform: scale(clamp(0.15.var(--scale), 1));
          }
      </style>
      Copy the code
    • Clamp (0.15, var(–scale), 1); This declaration is used to scale the text

    • Clamp (0.15,var(–scale),1) is to select the appropriate size value, and the parameters represent the minimum value, preferred value and maximum value respectively. If the preferred value is greater than 1, the returned value is 1; if the preferred value is less than 0.15, the returned value is 0.15

    • IntersectionObserver is used to monitor whether H2 is located in the viewport. E.element Sectionratio indicates the ratio of h2 element to the intersection area of the viewport. If it is less than 1, it indicates that the element is not completely located in the viewport. So the position:sticky property of H2 already comes into play

    • GetComputedStyle gets the style attribute of the element. The reason to use parseInt is because these values return XXPX strings that need to be converted to numbers

    • When the scroll bar is sliding down, when the sticky h2 element is in effect, let the element be scaled according to the ratio of the scrolling distance to the height of the element, to a certain extent, no scaling.

  • The second: scaling

    • <style>
          h2 {
            transform:matrix(var(--scale), 0.0.var(--scale), 0.0);
          }
      </style>
      Copy the code
    • Matrix (var(–scale), 0, 0, var(–scale), 0, 0

    • link