lang 속성에는 하나의 언어만 연결할 수 있습니다. 즉, 페이지에 여러 언어가 있더라도 <html>
속성은 언어를 하나만 가질 수 있습니다. lang
를 페이지의 기본 언어로 설정합니다.
<html lang="ar,en,fr,pt">...</html>
<html lang="ar">...</html>
링크
버튼과 마찬가지로 링크는 주로 텍스트 콘텐츠에서 액세스 가능한 이름을 가져옵니다. 링크를 만들 때 좋은 방법은 '여기' 또는 '자세히 알아보기'와 같은 구체적인 단어 대신 가장 의미 있는 텍스트를 링크 자체에 배치하는 것입니다.
Check out our guide to web performance <a href="/guide">here</a>.
Check out <a href="/guide">our guide to web performance</a>.
애니메이션이 레이아웃을 트리거하는지 확인
transform
이외의 항목을 사용하여 요소를 이동하는 애니메이션은 느릴 수 있습니다.
다음 예에서는 top
및 left
를 애니메이션 처리하고 transform
를 사용하여 동일한 시각적 결과를 얻었습니다.
.box { position: absolute; top: 10px; left: 10px; animation: move 3s ease infinite; } @keyframes move { 50% { top: calc(90vh - 160px); left: calc(90vw - 200px); } }
.box { position: absolute; top: 10px; left: 10px; animation: move 3s ease infinite; } @keyframes move { 50% { transform: translate(calc(90vw - 200px), calc(90vh - 160px)); } }
다음 두 가지 Glitch 예시에서 이를 테스트하고 DevTools를 사용하여 성능을 살펴볼 수 있습니다.
동일한 마크업을 사용하여 padding-top: 56.25%
를 aspect-ratio: 16 / 9
로 대체하고 aspect-ratio
를 지정된 비율 width
/ height
로 설정할 수 있습니다.
.container { width: 100%; padding-top: 56.25%; }
.container { width: 100%; aspect-ratio: 16 / 9; }
padding-top
대신 aspect-ratio
를 사용하면 훨씬 더 명확해지고 패딩 속성을 대대적으로 수정하여 일반적인 범위를 벗어난 작업을 하지 않습니다.
네, 생각하신 대로 프라미스의 순서를 체이닝하려고 reduce
를 사용하고 있습니다. 정말 똑똑해. 하지만 이 코드는 너무 스마트해서 사용하지 않는 것이 좋습니다.
하지만 위 코드를 비동기 함수로 변환할 때는 너무 순차적으로 작성하고 싶은 유혹이 생길 것입니다.
async function logInOrder(urls) { for (const url of urls) { const response = await fetch(url); console.log(await response.text()); } }
function markHandled(...promises) { Promise.allSettled(promises); } async function logInOrder(urls) { // fetch all the URLs in parallel const textPromises = urls.map(async (url) => { const response = await fetch(url); return response.text(); }); markHandled(...textPromises); // log them in sequence for (const textPromise of textPromises) { console.log(await textPromise); } }
reduce
비트가 쉽게 읽을 수 있지만 일반적이고 따분해 보이는 for 루프로 바뀌어 있죠.
Houdini 맞춤 속성 작성
다음은 맞춤 속성 (예: CSS 변수)을 설정하는 예입니다. 이제 문법 (유형), 초기 값 (대체), 상속 불리언 (상위 요소에서 값을 상속할지 여부)이 포함되어 있습니다. 현재 이를 실행하는 방법은 JavaScript의 CSS.registerProperty()
를 사용하는 것이지만 Chromium 85 이상에서는 CSS 파일에서 @property
문법이 지원됩니다.
CSS.registerProperty({ name: '--colorPrimary', syntax: '' , initialValue: 'magenta', inherits: false });
@property --colorPrimary { syntax: '' ; initial-value: magenta; inherits: false; }
이제 var(--colorPrimary)
를 통해 다른 CSS 맞춤 속성과 마찬가지로 --colorPrimary
에 액세스할 수 있습니다. 그러나 여기서 차이점은 --colorPrimary
가 문자열로만 읽히지 않는다는 것입니다. 데이터가 있습니다.
CSS backdrop-filter
는 반투명하거나 투명한 요소에 하나 이상의 효과를 적용합니다. 이를 이해하려면 아래 이미지를 살펴보세요.

.frosty-glass-pane { backdrop-filter: blur(2px); }

.frosty-glass-pane { opacity: .9; backdrop-filter: blur(2px); }
왼쪽 이미지는 backdrop-filter
가 사용되지 않거나 지원되지 않는 경우 중첩된 요소가 렌더링되는 방식을 보여줍니다. 오른쪽 이미지에는 backdrop-filter
를 사용하여 흐리게 처리 효과가 적용되어 있습니다. backdrop-filter
외에도 opacity
를 사용합니다. opacity
가 없으면 흐리게 처리할 항목이 없습니다. opacity
이 1
(전체적으로 불투명)로 설정되면 배경에 아무런 영향을 미치지 않는다는 것은 거의 말할 필요도 없습니다.
하지만 unload
이벤트와 달리 beforeunload
에는 합법적인 용도가 있습니다. 예를 들어 사용자가 페이지를 나가면 저장되지 않은 변경사항이 삭제된다고 경고하려는 경우 이 경우 사용자에게 저장되지 않은 변경사항이 있을 때만 beforeunload
리스너를 추가한 다음 저장되지 않은 변경사항이 저장된 직후에 삭제하는 것이 좋습니다.
window.addEventListener('beforeunload', (event) => { if (pageHasUnsavedChanges()) { event.preventDefault(); return event.returnValue = 'Are you sure you want to exit?'; } });
beforeunload
리스너를 추가합니다.
function beforeUnloadListener(event) { event.preventDefault(); return event.returnValue = 'Are you sure you want to exit?'; }; // A function that invokes a callback when the page has unsaved changes. onPageHasUnsavedChanges(() => { window.addEventListener('beforeunload', beforeUnloadListener); }); // A function that invokes a callback when the page's unsaved changes are resolved. onAllChangesSaved(() => { window.removeEventListener('beforeunload', beforeUnloadListener); });
beforeunload
리스너를 추가하고 필요하지 않을 때는 삭제합니다.
Cache-Control: no-store
사용 최소화
Cache-Control: no-store
는 웹 서버가 응답에 설정할 수 있는 HTTP 헤더로, 브라우저에 응답을 HTTP 캐시에 저장하지 말라고 지시합니다. 민감한 사용자 정보가 포함된 리소스(예: 로그인 페이지)에 사용해야 합니다.
각 입력 그룹 (.fieldset-item
)을 포함하는 fieldset
요소는 gap: 1px
를 사용하여 요소 간에 머리카락 선 테두리를 만듭니다. 복잡한 테두리 솔루션은 없습니다.
.grid { display: grid; gap: 1px; background: var(--bg-surface-1); & > .fieldset-item { background: var(--bg-surface-2); } }
.grid { display: grid; & > .fieldset-item { background: var(--bg-surface-2); &:not(:last-child) { border-bottom: 1px solid var(--bg-surface-1); } } }
자연스러운 그리드 래핑
가장 복잡한 레이아웃은 <main>
와 <form>
사이의 논리적 레이아웃 시스템인 매크로 레이아웃이었습니다.
<input type="checkbox" id="text-notifications" name="text-notifications" >
<label for="text-notifications"> <h3>Text Messages</h3> <small>Get notified about all text messages sent to your device</small> </label>
각 입력 그룹 (.fieldset-item
)을 포함하는 fieldset
요소는 gap: 1px
를 사용하여 요소 간에 머리카락 선 테두리를 만듭니다. 복잡한 테두리 솔루션은 없습니다.
.grid { display: grid; gap: 1px; background: var(--bg-surface-1); & > .fieldset-item { background: var(--bg-surface-2); } }
.grid { display: grid; & > .fieldset-item { background: var(--bg-surface-2); &:not(:last-child) { border-bottom: 1px solid var(--bg-surface-1); } } }
탭 <header>
레이아웃
다음 레이아웃은 거의 동일합니다. flex를 사용하여 세로 순서를 만듭니다.
<snap-tabs> <header> <nav></nav> <span class="snap-indicator"></span> </header> <section></section> </snap-tabs>
header { display: flex; flex-direction: column; }
.snap-indicator
는 링크 그룹과 함께 가로로 이동해야 하며 이 헤더 레이아웃은 이러한 단계를 설정하는 데 도움이 됩니다. 절대 위치로 배치된 요소가 없습니다.
조정된 유연성은 보다 정확한 중심 맞춤전용 전략입니다. place-content: center
와 달리 중앙 정렬 중에 하위 요소의 상자가 변경되지 않으므로 부드럽고 조용합니다. 최대한 부드럽게 모든 항목을 쌓고 중앙에 정렬하며 간격을 둡니다.
.gentle-flex {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1ch;
}
- 정렬, 방향, 배포만 처리
- 수정 및 유지보수를 한곳에서 모두 처리하세요.
- 갭은 n 하위 요소 간에 동일한 간격을 보장합니다.
- 코드 줄 수
매크로 및 마이크로 레이아웃 모두에 적합합니다.
사용
.gap-example {
display: grid;
gap: 10px;
gap: 2ch;
gap: 5%;
gap: 1em;
gap: 3vmax;
}
Gap에는 행과 열 모두에 사용되는 길이 1이 전달될 수 있습니다.
.grid { display: grid; gap: 10px; }
.grid { display: grid; row-gap: 10px; column-gap: 10px; }
Gap에는 행과 열에 사용되는 두 개의 길이를 전달할 수 있습니다.
.grid { display: grid; gap: 10px 5%; }
.grid { display: grid; row-gap: 10px; column-gap: 5%; }