>웹 프론트엔드 >CSS 튜토리얼 >inutes에서 다크 모드 토글 구축(실제로 작동함)

inutes에서 다크 모드 토글 구축(실제로 작동함)

Susan Sarandon
Susan Sarandon원래의
2024-11-10 03:01:02430검색

Build a Dark Mode Toggle in inutes (That Actually Works)

어두운 모드 토글을 구현하는 데 몇 시간을 소비했지만 페이지 새로 고침 시 눈이 멀 정도로 흰색으로 깜박이게 한 적이 있습니까? 아니면 사용자의 시스템 기본 설정을 완전히 무시했습니까? 응, 나도 마찬가지야. ?

사실입니다. 어두운 모드는 더 이상 유행하는 기능이 아닙니다. 밤에 코딩하는 사람이 늘어나고(유죄) 접근성이 점점 중요해짐에 따라 잘 구현된 다크 모드는 현대 웹사이트나 웹 앱에 사실상 필수입니다. 하지만 이를 올바르게 수행하는 것은 놀라울 정도로 까다로울 수 있습니다.

좋은 소식은요? 다양한 구현을 더듬고 localStorage와 씨름한 끝에 마침내 다음과 같은 다크 모드 토글 코드를 해독했습니다.

  • 사용자의 선호도를 실제로 기억합니다
  • 다시 로드할 때 잘못된 테마가 깜박이지 않습니다
  • 시스템 기본 설정에 따라 원활하게 재생됩니다
  • 구현하는 데 말 그대로 5분 정도 걸립니다

이 게시물에서는 실제로 사용하고 싶은 어두운 모드 토글을 구축하는 과정을 안내해 드리겠습니다. 지나치게 복잡한 솔루션이나 불필요한 종속성이 없습니다. 즉시 구현할 수 있는 깔끔하고 작동하는 코드만 있으면 됩니다.

전제 조건(필요한 것)

먼저 지루한 부분부터 처리하겠습니다. 하지만 짧게 진행하겠다고 약속드립니다!

아마도 이미 필요한 모든 것이 갖추어져 있지만, 우리가 같은 입장인지 확인하기 위해:

  • 기본 HTML(이 무엇인지 아시나요?)
  • 일부 CSS 지식(특히 CSS 변수 - 진행하면서 설명하겠습니다)
  • 바닐라 JavaScript(멋진 것은 아닙니다. 약속합니다)
  • 가장 선호하는 코드 편집기
  • 약 5분 정도의 시간(그리고 커피도 한잔 ♥)

우리가 만들고 있는 것

시작하기 전에 최종 결과를 간단히 살펴보겠습니다. 화려한 UI 라이브러리나 복잡한 설정이 필요하지 않습니다. 다음과 같은 간단하고 부드러운 토글만 있으면 됩니다.

이렇게 보이게 만드는 것에 대해 걱정하지 마세요. 중요한 부분은 완벽하게 작동한다는 것입니다. 먼저 기능에 중점을 두고, 원하는 대로 스타일을 지정할 수 있습니다.

가장 좋은 점은 무엇인가요? 우리가 구축하려는 모든 것은 다음과 함께 작동합니다.

  • 최신 브라우저(예, Safari도 마찬가지입니다!)
  • 시스템 다크 모드 기본 설정
  • 페이지 새로 고침(더 이상 흰색 화면이 깜박이지 않음)
  • 외부 의존성 제로

손을 더럽힐 준비가 되셨나요? 파운데이션부터 시작해 보세요!

재단 설립

자, 손을 더럽히자! 먼저 기본 구조를 설정하겠습니다.

HTML: 단순하게 유지하세요

아주 간단한 HTML부터 시작하겠습니다. 이 부분은 지나치게 생각할 필요가 없습니다:

<button>



<h3>
  
  
  The CSS
</h3>

<p>Here's where things get interesting. We'll use CSS variables (aka custom properties) to handle our color scheme. Drop this in your CSS file:<br>
</p>

<pre class="brush:php;toolbar:false">:root {
  --background: #ffffff;
  --text-primary: #222222;
  --toggle-bg: #e4e4e7;
  --toggle-hover: #d4d4d8;
}


[data-theme="dark"] {
  --background: #121212;
  --text-primary: #ffffff;
  --toggle-bg: #3f3f46;
  --toggle-hover: #52525b;
}

body {
  background-color: var(--background);
  color: var(--text-primary);
  transition: background-color 0.3s ease, color 0.3s ease;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.theme-toggle {
  border: none;
  padding: 0.5rem;
  border-radius: 9999px;
  background-color: var(--toggle-bg);
  cursor: pointer;
  transition: background-color 0.2s ease;
  align-self: flex-start;
  position: absolute;
  right: 20px;
}

.theme-toggle:hover {
  background-color: var(--toggle-hover);
}

.theme-toggle svg {
    transform-origin: center;
    transition: transform 0.3s ease;
}

.theme-toggle:active svg {
    transform: rotate(30deg);
}

h1 {
  display: flex;
}

.sun-icon {
  display: none;
  width: 24px;
  height: 24px;
}

.moon-icon {
  width: 24px;
  height: 24px;
}

[data-theme="dark"] .sun-icon {
  display: block;
}

[data-theme="dark"] .moon-icon {
  display: none;
}

전문가 팁: 클래스 대신 데이터 테마를 어떻게 사용하고 있는지 확인하세요. 이렇게 하면 속성의 용도가 매우 명확해지고 잠재적인 클래스 이름 충돌을 방지할 수 있습니다.

아이콘의 경우 자체 SVG를 사용하거나 즐겨찾는 아이콘 라이브러리에서 일부를 가져올 수 있습니다. 저는 간단한 것을 사용하는 것을 좋아해서 Chatgpt에게 이것을 생각해내라고 말했습니다:

<!-- Replace the empty SVGs with these -->
<svg>



<p>At this point, your toggle should look pretty decent, but it won't actually do anything yet. Don't worry though - in the next section, we'll add the JavaScript that makes it all work!</p>

<p><strong>A quick heads-up:</strong> I've kept the styling minimal on purpose. Feel free to spice it up with your own creative touches. Want a sliding animation? Go for it! Prefer a different icon style? Make it yours!</p>

<p>Ready to make this thing actually work? Let's move on to the JavaScript implementation!</p>

<h2>
  
  
  The JavaScript Implementation (Where It All Comes Together!)
</h2>

<p>Alright, this is where we make our toggle actually, you know... toggle. But don't worry - we're keeping it clean and simple.<br>
</p>

<pre class="brush:php;toolbar:false">const themeToggle = document.querySelector('.theme-toggle');


function toggleTheme() {
  const currentTheme = document.documentElement.getAttribute('data-theme');

  const newTheme = currentTheme === 'dark' ? 'light' : 'dark';

  document.documentElement.setAttribute('data-theme', newTheme);

  localStorage.setItem('theme', newTheme);
}

// Listen for clicks on our toggle
themeToggle.addEventListener('click', toggleTheme);


function initializeTheme() {
  const savedTheme = localStorage.getItem('theme');

  if (savedTheme) {
    document.documentElement.setAttribute('data-theme', savedTheme);
  } else {
    const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;

    document.documentElement.setAttribute(
      'data-theme',
      prefersDark ? 'dark' : 'light'
    );

    localStorage.setItem('theme', prefersDark ? 'dark' : 'light');
  }
}

// Run on page load
initializeTheme();

// Listen for system theme change

window.matchMedia('(prefers-color-scheme: dark)')
  .addEventListener('change', (e) => {
    // Only update if user hasn't manually set a preference
    if (!localStorage.getItem('theme')) {
      document.documentElement.setAttribute(
        'data-theme',
        e.matches ? 'dark' : 'light'
      );
    }
  });

실제로 꽤 멋진 일이 벌어지고 있으니 여기서 무슨 일이 일어나고 있는지 분석해 보겠습니다.

  1. 누군가 토글을 클릭하면 현재 테마를 확인하고 반대 테마로 전환합니다
  2. 선택 사항을 localStorage에 저장합니다(페이지 로드 간에 유지됨)
  3. 페이지가 처음 로드되면 다음을 수행합니다.
    • 저장된 기본 설정이 있는지 확인
    • 그렇지 않다면 시스템 테마를 확인해보세요
    • 적절한 테마를 적용하세요
  4. 보너스로 시스템 테마 변경 사항(예: 누군가 OS에서 다크 모드를 활성화하는 경우)을 듣습니다.

잘못된 테마의 플래시 방지

다음은 일반적인 문제입니다. 페이지가 로드될 때 사용자에게 잘못된 테마가 깜박이는 경우가 있습니다. 정말 짜증나죠?

귀하의 HTML:
<script>
  // Add this to your <head> before any style sheets
  (function() {
    const savedTheme = localStorage.getItem('theme');
    if (savedTheme) {
      document.documentElement.setAttribute('data-theme', savedTheme);
    } else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
      document.documentElement.setAttribute('data-theme', 'dark');
    }
  })();
</script>

다른 항목이 로드되기 직전에 실행되므로 성가신 플래시를 방지할 수 있습니다.

그리고... 바로 그거예요! 다음과 같은 기능을 갖춘 어두운 모드 토글이 있습니다.

  • 사용자 기본 설정 기억
  • 시스템 설정을 존중합니다
  • 잘못된 테마를 플래시하지 않습니다
  • 전환이 원활하게 작동합니다

더 좋게 만들고 싶으신가요? 좋은 상태에서 좋은 상태로 전환하는 데 도움이 되는 몇 가지 유용한 팁을 살펴보겠습니다.

더 나은 결과 만들기(세부 사항이 중요하기 때문에!)

중요하지만 종종 간과되는 몇 가지 개선 사항을 포함하여 '작동함'에서 '아름답게 작동함'으로 전환해 보겠습니다. 이는 전문적인 구현과 빠른 해킹을 구분하는 세부 사항입니다.

1. 키보드 접근성

우선, 기기와 상호작용하는 방식에 관계없이 모든 사람이 토글을 사용할 수 있도록 합시다.

// Add this to your existing JavaScript
themeToggle.addEventListener('keydown', (e) => {
    // Toggle on Enter or Space
    if (e.key === 'Enter' || e.key === ' ') {
        e.preventDefault();
        toggleTheme();
    }
});

2. 전환 비활성화

사용자가 모션 감소를 선호하는 경우 전환을 비활성화합니다.

@media (prefers-reduced-motion: reduce) {
  body {
    transition: none;
  }
}

3. 콘텐츠 변경 처리

많은 개발자가 놓치는 부분이 있습니다. 일부 콘텐츠는 테마에 따라 변경되어야 할 수도 있습니다. 밝은 모드/어두운 모드에 대한 다양한 버전의 이미지를 생각해 보세요.

// Add this to your toggleTheme function
function updateThemeSpecificContent(theme) {
    // Find all theme-aware images
    const themeImages = document.querySelectorAll('[data-theme-image]');

    themeImages.forEach(img => {
        const lightSrc = img.getAttribute('data-light-src');
        const darkSrc = img.getAttribute('data-dark-src');

        img.src = theme === 'dark' ? darkSrc : lightSrc;
    });
}

HTML에서 다음과 같이 사용하세요.

<img data-theme-image data-light-src="/path/to/light-logo.png" data-dark-src="/path/to/dark-logo.png" alt="inutes에서 다크 모드 토글 구축(실제로 작동함)">

4. 테마 불일치 방지

때때로 저장된 테마가 실제로 표시되는 테마와 동기화되지 않을 수 있습니다. 안전 확인을 추가해 보겠습니다.

<button>



<h3>
  
  
  The CSS
</h3>

<p>Here's where things get interesting. We'll use CSS variables (aka custom properties) to handle our color scheme. Drop this in your CSS file:<br>
</p>

<pre class="brush:php;toolbar:false">:root {
  --background: #ffffff;
  --text-primary: #222222;
  --toggle-bg: #e4e4e7;
  --toggle-hover: #d4d4d8;
}


[data-theme="dark"] {
  --background: #121212;
  --text-primary: #ffffff;
  --toggle-bg: #3f3f46;
  --toggle-hover: #52525b;
}

body {
  background-color: var(--background);
  color: var(--text-primary);
  transition: background-color 0.3s ease, color 0.3s ease;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.theme-toggle {
  border: none;
  padding: 0.5rem;
  border-radius: 9999px;
  background-color: var(--toggle-bg);
  cursor: pointer;
  transition: background-color 0.2s ease;
  align-self: flex-start;
  position: absolute;
  right: 20px;
}

.theme-toggle:hover {
  background-color: var(--toggle-hover);
}

.theme-toggle svg {
    transform-origin: center;
    transition: transform 0.3s ease;
}

.theme-toggle:active svg {
    transform: rotate(30deg);
}

h1 {
  display: flex;
}

.sun-icon {
  display: none;
  width: 24px;
  height: 24px;
}

.moon-icon {
  width: 24px;
  height: 24px;
}

[data-theme="dark"] .sun-icon {
  display: block;
}

[data-theme="dark"] .moon-icon {
  display: none;
}

5. 성능 최적화 트릭

다양한 테마에서 사용자 정의 글꼴을 로드할 때 레이아웃 변경을 방지하는 깔끔한 방법은 다음과 같습니다.

<!-- Replace the empty SVGs with these -->
<svg>



<p>At this point, your toggle should look pretty decent, but it won't actually do anything yet. Don't worry though - in the next section, we'll add the JavaScript that makes it all work!</p>

<p><strong>A quick heads-up:</strong> I've kept the styling minimal on purpose. Feel free to spice it up with your own creative touches. Want a sliding animation? Go for it! Prefer a different icon style? Make it yours!</p>

<p>Ready to make this thing actually work? Let's move on to the JavaScript implementation!</p>

<h2>
  
  
  The JavaScript Implementation (Where It All Comes Together!)
</h2>

<p>Alright, this is where we make our toggle actually, you know... toggle. But don't worry - we're keeping it clean and simple.<br>
</p>

<pre class="brush:php;toolbar:false">const themeToggle = document.querySelector('.theme-toggle');


function toggleTheme() {
  const currentTheme = document.documentElement.getAttribute('data-theme');

  const newTheme = currentTheme === 'dark' ? 'light' : 'dark';

  document.documentElement.setAttribute('data-theme', newTheme);

  localStorage.setItem('theme', newTheme);
}

// Listen for clicks on our toggle
themeToggle.addEventListener('click', toggleTheme);


function initializeTheme() {
  const savedTheme = localStorage.getItem('theme');

  if (savedTheme) {
    document.documentElement.setAttribute('data-theme', savedTheme);
  } else {
    const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;

    document.documentElement.setAttribute(
      'data-theme',
      prefersDark ? 'dark' : 'light'
    );

    localStorage.setItem('theme', prefersDark ? 'dark' : 'light');
  }
}

// Run on page load
initializeTheme();

// Listen for system theme change

window.matchMedia('(prefers-color-scheme: dark)')
  .addEventListener('change', (e) => {
    // Only update if user hasn't manually set a preference
    if (!localStorage.getItem('theme')) {
      document.documentElement.setAttribute(
        'data-theme',
        e.matches ? 'dark' : 'light'
      );
    }
  });

빠른 테스트 체크리스트

배송하기 전에 다음 시나리오를 테스트해 보세요.

  • ✅ 페이지 새로고침으로 올바른 테마가 유지됩니다
  • ✅ 시스템 테마 변경 사항이 적용됩니다(수동 기본 설정이 없는 경우)
  • ✅ 토글은 마우스와 키보드 모두에서 작동합니다
  • ✅ 로드 시 잘못된 테마가 깜박이지 않습니다
  • ✅ 전환이 원활함
  • ✅ 모든 주요 브라우저에서 작동합니다(예, Safari도 마찬가지입니다!)
  • ✅ 테마별 콘텐츠가 올바르게 업데이트됩니다

주의해야 할 일반적인 문제

  1. 제3자 콘텐츠: 일부 삽입된 콘텐츠는 테마를 따르지 않을 수 있습니다. 다음과 같이 처리하십시오.
<script>
  // Add this to your <head> before any style sheets
  (function() {
    const savedTheme = localStorage.getItem('theme');
    if (savedTheme) {
      document.documentElement.setAttribute('data-theme', savedTheme);
    } else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
      document.documentElement.setAttribute('data-theme', 'dark');
    }
  })();
</script>
  1. 투명도가 적용된 이미지: 배경에 따라 잘못 보일 수 있습니다.
// Add this to your existing JavaScript
themeToggle.addEventListener('keydown', (e) => {
    // Toggle on Enter or Space
    if (e.key === 'Enter' || e.key === ' ') {
        e.preventDefault();
        toggleTheme();
    }
});

그렇습니다! 이제 챔피언과 같은 다양한 시나리오를 처리하는 강력하고 접근 가능하며 사용자 친화적인 다크 모드 구현이 가능해졌습니다.

결론

자, 거기 있어요! 우리는 작동할 뿐만 아니라 정말 잘 작동하는 다크 모드 토글을 구축했습니다.

우리가 성취한 내용을 빠르게 요약해 보겠습니다.

  • 사용자의 선호도를 실제로 기억하는 토글 ?
  • 두려운 플래시 없이 테마 간 원활한 전환 ⚡
  • 제대로 작동하는 시스템 환경설정 감지 ?
  • 처음부터 접근성 내장 ♿
  • 빠른 속도를 유지하기 위한 성능 최적화 ?‍♂️

여기에서 어디로 가야 할까요?

이 코드를 자유롭게 사용하여 나만의 코드로 만들어 보세요. 멋진 애니메이션을 추가하거나, 다양한 색상 구성을 시도하거나, 기존 디자인과 통합할 수도 있습니다. 우리가 구축한 기반은 귀하가 던지는 어떤 창의적인 아이디어도 처리할 수 있을 만큼 견고합니다.

마지막으로 한 가지...

어두운 모드는 작은 세부 사항처럼 보일 수 있지만 이러한 작은 터치를 통해 사용자 경험에 관심을 기울이고 있음을 알 수 있습니다. 게다가 정말 멋지네요. 좋은 다크 모드를 좋아하지 않는 사람이 있을까요?

이 내용이 도움이 되었다면 다른 개발자와 자유롭게 공유해 주세요. 그리고 멋진 개선 사항이 있으면 알려주세요!


연결을 유지하자! ?

이 가이드가 마음에 들었고 더 많은 웹 개발 팁, 해킹, 프로그래밍에 대한 아빠의 농담을 더 알고 싶다면 X에서 저와 함께 놀러 오세요! 개발자 여정에서 얻은 빠른 팁, 코딩 통찰력, 실제 솔루션을 공유합니다.

? @Peboydcoder를 팔로우하세요

다음 주제에 대해 정기적으로 게시합니다.

  • 웹 개발 팁과 요령
  • 프런트엔드 모범 사례
  • UI/UX 인사이트
  • 그렇습니다. 다크 모드 감상 게시물이 더 많나요?

들러서 인사하세요! 더 나은 웹 경험을 구축하는 데 관심이 있는 동료 개발자들과 소통하는 것은 언제나 즐겁습니다.


위 내용은 inutes에서 다크 모드 토글 구축(실제로 작동함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.