programing

타겟팅 위치: 현재 '고임' 상태인 끈적거리는 요소

javamemo 2023. 10. 27. 21:39
반응형

타겟팅 위치: 현재 '고임' 상태인 끈적거리는 요소

position: sticky는 현재 일부 모바일 브라우저에서 작동하므로 페이지로 메뉴 바를 스크롤할 수 있지만 사용자가 스크롤할 때마다 뷰포트 상단에 붙어 있습니다.

하지만 만약 여러분이 끈적거리는 메뉴바가 현재 '붙을' 때마다 약간의 스타일을 바꾸고 싶다면 어떻게 해야 할까요?예를 들어, 페이지를 스크롤할 때마다 막대에 둥근 모서리가 있기를 원할 수도 있지만, 뷰포트 상단에 붙자마자 맨 위의 둥근 모서리를 없애고 그 아래에 약간의 그림자를 추가합니다.

어떤 종류의 의사 선택기가 있습니까?::stuck를 포함하는 요소를 대상으로 합니다.position: sticky 그리고 현재 고착되어 있습니까?아니면 브라우저 공급업체가 이와 같은 것을 파이프라인에 가지고 있습니까?만약 그렇지 않다면 어디에 요청해야 합니까?

NB. javascript 솔루션은 모바일에서 보통 단 하나만 얻을 수 있기 때문에 이것에 좋지 않습니다.scroll사용자가 손가락을 놓으면 스크롤 임계값이 통과된 정확한 순간을 JS가 알 수 없습니다.

현재 '고착'된 요소에 대해 제안되고 있는 셀렉터가 없습니다.Positioned Layout 모듈은 다음과 같습니다.position: sticky정의되어 있습니다. 이러한 선택기에 대해서도 언급하지 않습니다.

CSS에 대한 기능 요청은 www 스타일 메일링 리스트에 게시할 수 있습니다.나는 A라고 믿습니다.:stuck사이비 클래스는 a보다 더 말이 됩니다.::stuck사이비 element입니다. 그 상태에서 원소 자체를 목표로 삼으려고 하니까요., a.:stuck의사 클래스는 얼마 전에 논의되었습니다. 주된 합병증은 렌더링된 또는 계산된 스타일에 기반하여 일치를 시도하는 제안된 선택기에 대한 것으로 발견되었습니다. 즉 원형 의존성입니다.

의 의 .:stuck의사 클래스, 순환성의 가장 간단한 경우는 다음과 같은 CSS로 발생합니다.

:stuck { position: static; /* Or anything other than sticky/fixed */ }
:not(:stuck) { position: sticky; /* Or fixed */ }

그리고 해결하기 어려운 엣지 케이스가 더 많이 있을 수 있습니다.

일반적으로 특정 레이아웃 상태를 기준으로 일치하는 선택기를 사용하는 것이 좋다는 것에는 동의하지만, 불행하게도 이러한 사소한 구현을 가능하게 하는 주요 제한 사항이 존재합니다.저는 이 문제에 대한 순수한 CSS 해결책에 대해 조만간 숨을 죽이고 싶지 않습니다.

어떤 경우에는 단순한.IntersectionObserver상황이 적절한 플러시가 아닌 루트 컨테이너 외부의 픽셀 또는 두 개에 달라붙을 수 있는 경우, 를 사용할 수 있습니다.가장자리 바로 너머에 앉으면 관찰자가 총을 쏘고 우리는 도망갑니다.

const observer = new IntersectionObserver( 
  ([e]) => e.target.toggleAttribute('stuck', e.intersectionRatio < 1),
  {threshold: [1]}
);

observer.observe(document.querySelector('nav'));

요소를 용기 밖으로 바로 집어넣습니다.top: -2px, 그 다음에 목표물은stuck속성...

nav {
  background: magenta;
  height: 80px;
  position: sticky;
  top: -2px;
}
nav[stuck] {
  box-shadow: 0 0 16px black;
}

예: https://codepen.io/anon/pen/vqyQEK

저는 '고착된' 요소를 스타일링 할 수 있는 순수한 CSS 솔루션을 원했습니다.::stuck유사 selector이 존재합니다(아, 2021년에는 여전히 존재하지 않습니다).

저는 JS 없이도 효과를 얻고 제 요구에 맞는 순수한 CSS 해킹을 만들었습니다.그것은 두 개의 요소 복사를 통해 작동합니다. 하나는sticky다른 하나는 그렇지 않습니다.unstuck1), 그리고 이 후자는 그것을 덮고 있습니다.sticky스크롤할 때까지 요소를 선택합니다.

데모: https://codepen.io/TomAnthony/pen/qBqgErK

대체 데모: https://codepen.io/TomAnthony/pen/mdOvJYw (이 버전은 제가 원했던 것입니다. 저는 끈적거리는 항목이 'stuck'일 때만 나타나기를 원했습니다. 중복 콘텐츠가 없다는 것을 의미하기도 합니다.)

HTML:

<div class="sticky">
    <div class="unstuck">
        <div>
        Box header. Italic when 'stuck'.
        </div>
    </div>
    <div class="stuck">
        <div>
        Box header. Italic when 'stuck'.
        </div>
    </div>
</div>

CSS:

.sticky {
    height: 20px;
    display: inline;
    background-color: pink;
}

.stuck {
    position: -webkit-sticky;
    position: sticky;
    top: 0;
    height: 20px;
    font-style: italic;
}

.unstuck {
    height: 0;
    overflow-y: visible;
    position: relative;
    z-index: 1;
}

.unstuck > div {
    position: absolute;
    width: 100%;
    height: 20px;
    background-color: inherit;
}

구글 개발자 블로그의 누군가IntersectionObserver로 실행 가능한 자바스크립트 기반 솔루션을 찾았다고 주장합니다.

관련 코드 비트:

/**
 * Sets up an intersection observer to notify when elements with the class
 * `.sticky_sentinel--top` become visible/invisible at the top of the container.
 * @param {!Element} container
 */
function observeHeaders(container) {
  const observer = new IntersectionObserver((records, observer) => {
    for (const record of records) {
      const targetInfo = record.boundingClientRect;
      const stickyTarget = record.target.parentElement.querySelector('.sticky');
      const rootBoundsInfo = record.rootBounds;

      // Started sticking.
      if (targetInfo.bottom < rootBoundsInfo.top) {
        fireEvent(true, stickyTarget);
      }

      // Stopped sticking.
      if (targetInfo.bottom >= rootBoundsInfo.top &&
          targetInfo.bottom < rootBoundsInfo.bottom) {
       fireEvent(false, stickyTarget);
      }
    }
  }, {threshold: [0], root: container});

  // Add the top sentinels to each section and attach an observer.
  const sentinels = addSentinels(container, 'sticky_sentinel--top');
  sentinels.forEach(el => observer.observe(el));
}

제가 직접 복제를 해본 적은 없지만, 이 문제로 인해 비틀거리는 사람에게 도움이 될 수도 있습니다.

스타일링을 위해 js 핵을 사용하는 것을 별로 좋아하지 않지만(예: BoudingClientRect 가져오기, 스크롤 듣기, 듣기 크기 조정), 이것이 현재 문제를 해결하는 방법입니다.이 솔루션은 최소화/최대화 가능한 내용(<details>)을 가진 페이지, 중첩 스크롤 또는 실제 곡선 공과 관련된 문제가 발생합니다.그렇기는 하지만, 문제가 간단한 경우에 대한 간단한 해결책이기도 합니다.

let lowestKnownOffset: number = -1;
window.addEventListener("resize", () => lowestKnownOffset = -1);

const $Title = document.getElementById("Title");
let requestedFrame: number;
window.addEventListener("scroll", (event) => {
    if (requestedFrame) { return; }
    requestedFrame = requestAnimationFrame(() => {
        // if it's sticky to top, the offset will bottom out at its natural page offset
        if (lowestKnownOffset === -1) { lowestKnownOffset = $Title.offsetTop; }
        lowestKnownOffset = Math.min(lowestKnownOffset, $Title.offsetTop);
        // this condition assumes that $Title is the only sticky element and it sticks at top: 0px
        // if there are multiple elements, this can be updated to choose whichever one it furthest down on the page as the sticky one
        if (window.scrollY >= lowestKnownOffset) {
            $Title.classList.add("--stuck");
        } else {
            $Title.classList.remove("--stuck");
        }
        requestedFrame = undefined;
    });
})

위의 요소가 있을 때를 위한 컴팩트한 방법.position:sticky요소.속성을 설정합니다.stuckCSS에서 일치시킬 수 있는header[stuck]:

HTML:

<img id="logo" ...>
<div>
  <header style="position: sticky">
    ...
  </header>
  ...
</div>

JS:

if (typeof IntersectionObserver !== 'function') {
  // sorry, IE https://caniuse.com/#feat=intersectionobserver
  return
}

new IntersectionObserver(
  function (entries, observer) {
    for (var _i = 0; _i < entries.length; _i++) {
      var stickyHeader = entries[_i].target.nextSibling
      stickyHeader.toggleAttribute('stuck', !entries[_i].isIntersecting)
    }
  },
  {}
).observe(document.getElementById('logo'))

언급URL : https://stackoverflow.com/questions/25308823/targeting-positionsticky-elements-that-are-currently-in-a-stuck-state

반응형