반응이 빠른 영국 방송사 내비게이션과 잡지 스타일 만들기!!
42007 단어 navintersectionobserverresponsivebbc
배경.
최근에 내가 친구의 사이트를 처음부터 다시 설계할 때, 나는 신속한 내비게이션을 위해 오래된 햄버거와는 다른 일을 하기로 결정했다.나는 뷰포트의 폭이 줄어들면서 내비게이션 항목이 메인 내비게이션에서 사라지고 보조 내비게이션에 나타나는 방식을 정말 좋아한다.
한동안 나는 그들이 자바스크립트를 사용하고 있는 줄 알았다.그러나 그들의 사이트를 방문할 때 JS를 닫은 후에 나는 놀랍게도 그것이 여전히 일하고 있다는 것을 발견했다.사실은 그들이
grid
와 일련의 media
조회를 사용하여 원하는 효과를 얻었다는 것을 증명한다.나는 이미 Smashing Magazine에서 기본 기능을 다시 만들었다. 자신의 기능을 구축하는 참고로 마음대로 사용하세요!this codepen JS 노선을 사용하지만 점진적인 강화 기능이 있어 JS가 적은 상황에서 완전히 중단되지 않는다.고맙습니다. 그곳에는 훌륭한 사람들BBC이 그들의 많은 구성 요소에 지원을 해 주었습니다. (접근성을 고려해서!)만약 내가 잘못하지 않았다면, 초자연적인 경외심을 불러일으키는 사람들이 이 활동에 참여했을 것이다. 그래서 너는 이것이 질이라는 것을 안다.
BBC 담당자는 이 구성 요소를 published guidelines and mini-tutorials라고 하는데, 다음과 같은 상황에서도 이 구성 요소는 그 목적을 충족시켜야 한다(즉, 사용자에게 내비게이션 링크 세트를 제공한다).
- No JavaScript: The functionality must be available to users whose browsers are not running JavaScript
- JavaScript but no IntersectionObserver: The IntersectionObserver API is the most efficient way to allot a suitable number of promoted navigation links within the available space. These links must still be available where the browser does not support IntersectionObserver.
이 규칙들을 기억하고 우리 자신의 버전을 구축하자!전체 과정 중 언제든지 Masthead를 참고하여 당신이 정확한 궤도에 있을 수 있도록 하세요!
this codepen
HTML 및 CSS 추가
우리는 우리의 내비게이션을 점차적으로 강화하기를 희망하기 때문에 우리는 먼저 가장 간단한 버전을 구축하고 모든 내비게이션 항목을 시종일관 표시하여 모든 사용자가 우리의 모든 정보를 방문할 수 있도록 할 것이다!
HTML부터 시작하겠습니다.
<header>
<nav aria-label="Our Site">
<a href="">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 14l9-5-9-5-9 5 9 5z"></path>
<path d="M12 14l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 14l9-5-9-5-9 5 9 5zm0 0l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14zm-4 6v-7.5l4-2.222"></path>
</svg>
</a>
<div class="main-nav">
<ul>
<li data-index="0">
<a href="">Link 1</a>
</li>
<li data-index="1">
<a href="">Link 2</a>
</li>
<li data-index="2">
<a href="">Link 3</a>
</li>
<li data-index="3">
<a href="">Link 4</a>
</li>
<li data-index="4">
<a href="">Link 5</a>
</li>
<li data-index="5">
<a href="">Link 6</a>
</li>
<li data-index="6">
<a href="">Link 7</a>
</li>
<li data-index="7">
<a href="">Link 8</a>
</li>
<li data-index="8">
<a href="">Link 9</a>
</li>
<li data-index="9">
<a href="">Link 10</a>
</li>
<li data-index="10">
<a href="">Link 11</a>
</li>
</ul>
</div>
</nav>
</header>
바로 이것header
이다. 나는 포장기 유형의 스타일을 응용할 것이다. 내가
에서 본 첫 번째svg와 nav
자체는 하나ul
와 11개 항목으로 구성된다.목록 항목마다 사용자 정의 data-index
속성을 추가했습니다. 나중에 IntersectionObserver
스타일을 전환할 때 이 속성을 사용합니다.지금 당신은 그것이 세계에서 가장 아름다운 내비게이션 장치가 아니라는 것을 알게 될 것이다.사실 그것은 보잘것없는ol목록처럼 보인다. (nav는 보통 그렇기 때문이다.)일부 CSS를 추가하여 이 점을 개선할 것입니다. (여기 스타일도 Codepen의 '리셋' 기본 스타일로 작성되었음을 기억하십시오.)
header {
position: relative;
margin-right: auto;
margin-left: auto;
background-color: burlywood;
padding: 1rem 4rem 2rem;
max-width: 64rem;
color: darkslategray;
font-family: Arial, Helvetica, sans-serif;
font-weight: 900;
}
nav {
display: flex;
position: relative;
align-items: center;
justify-content: center;
}
svg {
width: 5rem;
height: 5rem;
}
nav div {
margin-left: 3rem;
}
ul {
display: flex;
flex-wrap: wrap;
list-style: none;
padding: 1rem;
}
li {
padding-top: 1rem;
padding-left: 2rem;
}
a {
display: block;
position: relative;
text-decoration: none;
white-space: nowrap;
color: inherit;
}
a:focus {
outline: 2px dashed white;
outline-offset: 0.25rem;
}
ul a:hover {
transform: rotate(-3deg);
}
할 수 있다!이제 괜찮아졌어!여기서 주의해야 할 것은 모든 스타일(예를 들어 간격, 색깔, 정지 효과)은 완전히 임의이다.유일하게 진정으로 중요한 것은 flex
와 flex-wrap: wrap
의 설정ul
이다.이렇게 하면 탐색 항목이 뷰포트 너비의 감소에 따라 둘러싸일 수 있습니다.이것들이 있으면 우리의 가장 기본적인 응답 네비게이션이 완성된다!또는
flex
를 피하고 싶다면 구파의 방식으로 똑같은 포장 행위를 완성하고 모든 요소에 float: left
를 설정할 수 있다.단, 우리는 계속 사용할 것이다flex
.이제 사용자가 JS를 활성화한 상태에서 추가 기능을 추가합니다.뷰포트 너비가 줄어들면 기본 내비게이션에서 숨겨진 항목을 보조 내비게이션의 한 유형으로 주 내비게이션에 추가할 수 있습니다.
이 추가 항목의 표시를 우리
nav
의 끝 표시 앞에 두자.[...]
</div>
<div class="nav__more-item" style="display: none;">
<a href="#secondary-nav" role="button" aria-haspopup="true" aria-expanded="false">
<span class="visually-hidden">More</span>
<span aria-hidden="true">More</span>
</a>
</div>
</nav>
</header>
전체div
에 display: none;
가 있는 스타일 속성이 있음을 주의하십시오.사용자가 JS가 없으면 이 기능을 보여주고 싶지 않다는 것을 기억하라.따라서 기본값display
을 none
로 설정하고 나중에 JS를 통해 변경합니다.이 글의 CSS에는 작은 스톱 효과와 시각적 숨김 요소에 대한 접근 방식이 포함될 것이다. 나는 그 중에서 다음과 같은 것을 알게 되었다.
.nav__more-item {
padding-top: 1rem;
}
.nav__more-item a:hover {
background: darkslategray;
color: burlywood;
}
.visually-hidden {
position: absolute;
margin: 0;
border: 0;
padding: 0;
width: 1px;
height: auto;
overflow: hidden;
white-space: nowrap;
clip: rect(0 0 0 0);
}
이제 실제 메뉴 자체에 HTML을 추가하고 nav
오른쪽 바깥쪽에 HTML을 놓고 header
표시를 끝내기 전에:[...]
</nav>
<div id="secondary-nav" class="secondary-nav" style="display: none;">
<ul class="secondary-nav__list">
<li data-index="0">
<a href="">Link 1</a>
</li>
<li data-index="1">
<a href="">Link 2</a>
</li>
<li data-index="2">
<a href="">Link 3</a>
</li>
<li data-index="3">
<a href="">Link 4</a>
</li>
<li data-index="4">
<a href="">Link 5</a>
</li>
<li data-index="5">
<a href="">Link 6</a>
</li>
<li data-index="6">
<a href="">Link 7</a>
</li>
<li data-index="7">
<a href="">Link 8</a>
</li>
<li data-index="8">
<a href="">Link 9</a>
</li>
<li data-index="9">
<a href="">Link 10</a>
</li>
<li data-index="10">
<a href="">Link 11</a>
</li>
</ul>
</div>
</header>
기본값display
을 none
로 설정했습니다.이제 좀 더 예쁘게 보이도록 CSS를 추가하겠습니다.
.secondary-nav__list {
position: absolute;
top: 75%;
right: 0;
flex-direction: column;
align-items: center;
transform: translateX(-7%);
border-radius: 0.77rem;
box-shadow: 0 13px 27px -5px rgba(50, 50, 93, 0.25),
0 8px 16px -8px rgba(0, 0, 0, 0.3), 0 -6px 16px -6px rgba(0, 0, 0, 0.025);
background-color: darkslategray;
padding: 1rem 2rem 2rem;
min-width: 5rem;
height: auto;
color: burlywood;
}
.secondary-nav__list::before {
content: '';
display: block;
position: absolute;
top: 1px;
left: 50%;
transform: translate(-50%, -100%);
border-right: 15px solid transparent;
border-bottom: 15px solid darkslategray;
border-left: 15px solid transparent;
width: 0;
height: 0;
}
.secondary-nav__list li {
padding-left: 0;
}
탐색에 필요한 모든 HTML 및 CSS를 작성했습니다.지금부터 JS를 통해 일부 CSS를 적용할 예정입니다.우리 시작합시다!Heroicons
JS 추가
여기 있는 거의 모든 JS는 위에서 링크된 프레젠테이션 헤더를 위한 JS를 기반으로 한다.그래서 모든 공로는 창조 과정에서 구원의 손길을 뻗친 사람들에게 돌아간다.그것은 또한 통일되지 않고 유용한 평론도 포함하기 때문에 더 많은 해명이 필요하다면.
기본 스타일을 설정해서 버전을 시작합시다.Dell은 다음을 수행할 것입니다.
overflow-x
을 auto
로 설정하면 사용자가 브라우저에서 지원하지 않는 IntersectionObserver
상황에서도 모든 메뉴 항목을 스크롤하고 볼 수 있습니다.hidden
가 지원되는 경우 이 스타일은 나중에 IntersectionObserver
로 설정됩니다.flex-wrap
를 nowrap
로 설정하면 뷰포트 너비가 감소할 때 항목이 단순히 줄을 바꾸지 않습니다.display
블록을 설정합니다.var mainNav = document.querySelector('.main-nav');
mainNav.style.overflowX = 'auto';
mainNav.firstElementChild.style.flexWrap = 'nowrap';
var moreMenuItem = document.querySelector('.nav__more-item');
moreMenuItem.style.display = 'block';
위대하다현재 우리가 이전 절에 추가한 더 많은 내비게이션 항목을 보실 수 있습니다.이제 이벤트 탐지기를 추가하여 click
의 보조 탐색 메뉴를 표시/숨깁니다.var moreMenuLink = moreMenuItem.querySelector('a');
var secondaryNav = document.querySelector('.secondary-nav');
moreMenuLink.addEventListener('click', function (e) {
e.preventDefault();
var expanded = moreMenuLink.getAttribute('aria-expanded') === 'true' || false;
moreMenuLink.setAttribute('aria-expanded', !expanded);
var open = secondaryNav.style.display === 'flex' || false;
secondaryNav.style.display = open ? 'none' : 'flex';
if (!open) {
var firstVisibleItem = secondaryNav.querySelector('li[style="display: block;"] a');
firstVisibleItem.focus();
}
});
또한 이벤트 탐지기 두 개keydown
를 추가합니다. 하나는 메뉴 링크에 유사하게 button
를 표시하고 보조 네비게이션space
을 열고 다른 하나는 보조 네비게이션에 닫기esc
:moreMenuLink.addEventListener('keydown', function (e) {
if (e.keyCode === 32) {
e.preventDefault();
moreMenuLink.click();
}
});
secondaryNav.addEventListener('keydown', function (e) {
if (e.keyCode === 27) {
e.preventDefault();
moreMenuLink.setAttribute('aria-expanded', false);
secondaryNav.style.display = 'none';
moreMenuLink.focus();
}
});
check it out 추가
IntersectionObserver
이제 엔딩할 때가 왔다--무대를 떠나라IntersectionObserver
!본고는 API의 개념과 기능에 대해 어느 정도 알고 있다고 가정합니다. 만약에 제가 강력하게 추천한 깊이 있는 해석을 얻고 싶다면 .
우선, 브라우저가 그것을 지원하는지 확인하고, 주 내비게이션에 설정된
overflow-x
을 닫습니다.동시에 우리는 관찰자를 위해 설정을 설정해야 한다.주의, 우리는 관측자의 root
속성을 div
로 설정하여 포장주 내비게이션ul
에 사용하고 있다.if ('IntersectionObserver' in window) {
mainNav.style.overflowX = 'hidden';
var observerSettings = {
root: mainNav,
threshold: 0.98
}
이제 함수를 정의하여 교차가 발생할 때마다 함수를 호출할 수 있도록 관찰자에게 전달합니다. var secondaryNavItems = secondaryNav.querySelectorAll('li');
var callback = function (items, observer) {
Array.prototype.forEach.call(items, function(item) {
var index = parseInt(item.target.dataset.index);
if (item.intersectionRatio > 0.98) {
item.target.style.visibility = 'visible';
secondaryNavItems[index].style.display = 'none';
} else {
item.target.style.visibility = 'hidden';
secondaryNavItems[index].style.display = 'block';
}
});
};
관찰 항목data-index
속성의 값을 검사하여 렌더링 순서의 0 인덱스인 보조 탐색에 표시할 항목을 결정합니다.이 두 목록의 항목이 같은 순서로 나타나기 때문에, 우리는 그 색인을 사용하여 보조 네비게이션 목록에서 정확한 항목을 찾을 수 있다.마지막으로 우리는 설정을 사용하여 관찰자를 초기화하고 각 주요 내비게이션 항목을 리셋하고 호출한다
observe
. var mainNavItems = mainNav.querySelectorAll('li');
var observer = new IntersectionObserver(callback, observerSettings);
Array.prototype.forEach.call(mainNavItems, function(item) {
observer.observe(item);
});
}
봐라!이렇게 해서 우리의 관측자와 모든 응답이 민감하고 햄버거가 없는 내비게이션 표시줄이 끝났다!!방주: 내가 채식 쌍관어를 계속 하고 있을지도 모른다는 것을 방금 깨달았어. facepalm 이모티콘을 삽입했어.
this really great write up by Heather Weaver
결론
나는 이런 일이 어떻게 작동하는지 정말 잘 알고 싶다. 내가 설정
flex
한 잘못된 요소를 제외하고는 짧은 분노가 나타난다.그래서 나는 이 작은 문장이 다른 사람들의 분노를 줄이고 비슷한 것을 구축하고자 하는 모든 사람들을 도울 수 있기를 바란다.질문이나 의견이 있으면 언제든지 연락 주십시오즐겁게 놀았어!!
Reference
이 문제에 관하여(반응이 빠른 영국 방송사 내비게이션과 잡지 스타일 만들기!!), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/tmns/build-a-responsive-nav-bbc-smashing-magazine-style-57ln텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)