wave
Code

Áp dụng Dark Mode cho Favicon

Dạo này thiết kế lại logo cho trang web, mình có gặp phải vấn đề favicon không hiển thị tốt với những trình duyệt sử dụng dark mode. Nếu như ở phần nội dung trang web, chúng ta có thể kiểm soát mọi thứ từ kích thước cho đến độ tương phản màu sắc của logo. Thế nhưng với favicon thì không, cấu hình giao diện của trình duyệt phụ thuộc vào người dùng. Lúc này bạn buộc phải thiết kế favicon sao cho tương phản tốt ở cả Dark mode và Light mode.

Thông thường favicon / logo của trang web thì không thể thay đổi dễ dàng (vì vấn đề nhận dạng thương hiệu) vậy nên phương án thiết kế lại favicon là không khả thi. Sau một hồi mày mò tìm hiểu, mình tìm được một số giải pháp giải quyết vấn đề, nay chia sẻ lại với mọi người.

Favicon là gì?

Favicon – (Favorite Icon) là biểu tượng của website. Đó là một icon thu nhỏ ở góc trên cùng của tab trình duyệt, hiển thị trước tên trang web. Favicon thông thường sẽ được thiết kế trùng với logo website như 1 phần của nhận dạng thương hiệu. Định dạng của favicon thường ở dạng hình ảnh với kích nhỏ: .ico, .png, .svg,…

Hiện nay hầu hết các trình duyệt sẽ tự động sử dụng favicon mặc định ở đường dẫn /favicon.ico nếu bạn không khai báo favicon cho trang web ở phần <head>.

<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">

Áp dụng Dark Mode favicon

Để áp dụng Dark Mode favicon, vấn đề khó khăn nhất là làm sao nhận biết người dùng đang sử dụng Dark Mode trên trình duyệt của họ. May thay, vấn đề này được giải quyết trong với CSS media query thần thánh: prefers-color-scheme

Ở bài này sẽ trình bày 2 phương pháp ứng dụng Dark Mode favicon thông qua CSS media query.

Về vấn đề tương thích thì hiện nay có đến hơn 82% các trình duyệt đã hỗ trợ CSS media query này, và độ phổ biến sẽ càng tăng trong tương lai.

Hiện này có đến hơn 82% trình duyệt đã hỗ trợ CSS query prefers-color-scheme
Hiện này có đến hơn 82% trình duyệt đã hỗ trợ CSS query prefers-color-scheme

Áp dụng Dark Mode cho SVG favicon

Như đã đề cập ở phần giới thiệu về Favicon thì định dạng SVG cũng có thể được sử dụng làm favicon cho trang web. Nếu trang web của bạn có sử dụng SVG làm favicon thì hãy thử phương pháp này nhé, còn không hãy áp dụng phương pháp tiếp theo.

Giải pháp cho SVG favicon ở đây là chúng ta sẽ nhúng mã CSS vào tệp .SVG qua thẻ <style>.

Để sử dụng SVG làm favicon, bạn chèn đoạn code sau vào nội dung thẻ <head>. Trong đó favicon.svg là tệp favicon của bạn.

<link rel="icon" type="image/svg+xml" href="/favicon.svg">

Trong nội dung tệp SVG, chúng ta chèn thêm mã CSS trong thẻ <style>. Ý tưởng cơ bản là mặc định CSS sẽ đổ màu bình thường ở Light Mode, khi phát hiện Dark Mode sẽ sử dụng mã CSS trong @media (prefers-color-scheme: dark) { ... }. Lúc này tệp SVG sẽ hiển thị theo mã CSS đã cấu hình cho Dark Mode favicon. Ví dụ như sau:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 800 800" width="100" height="100">
	<style>
		#path1_id, #path2_id {
			fill:#e52d2a;
		}
		#path3_id{
			fill:013fcb;
		}
		@media (prefers-color-scheme: dark) {
			#path1_id, #path2_id,#path3_id {
				fill:white;
			}
		}
	</style>
<defs>
	<path id="path1_id" d="M96.57 10.2L97.85 10.43L99.08 10.76L100.29 11.17L101.45 11.66L102.32 12.1L339.3 148.92L339.3 148.95L339.94 149.33L340.96 150.05L341.93 150.83L342.84 151.68L343.68 152.59L344.47 153.56L345.18 154.58L345.83 155.65L346.4 156.77L346.89 157.93L347.3 159.13L347.62 160.37L347.86 161.64L348 162.94L348.05 164.27L348 165.6L347.86 166.9L347.62 168.17L347.3 169.41L346.89 170.61L346.4 171.77L345.83 172.89L345.18 173.96L344.47 174.98L343.68 175.95L342.84 176.86L341.93 177.7L340.96 178.49L339.94 179.2L339.84 179.27L220.77 248.01L220.76 248L220.73 248.02L219.61 248.59L218.45 249.08L217.25 249.49L216.01 249.82L214.74 250.05L213.44 250.2L212.11 250.25L210.78 250.2L209.48 250.05L208.21 249.82L206.97 249.49L205.77 249.08L204.61 248.59L203.49 248.02L202.42 247.38L201.4 246.66L200.43 245.88L199.52 245.03L198.67 244.12L197.89 243.15L197.17 242.13L196.85 241.6L196.83 241.59L78.29 36.28L77.8 35.31L77.3 34.15L76.89 32.95L76.57 31.71L76.33 30.44L76.19 29.14L76.14 27.81L76.19 26.48L76.33 25.18L76.57 23.91L76.89 22.67L77.3 21.47L77.8 20.3L78.37 19.19L79.01 18.12L79.73 17.1L80.51 16.13L81.36 15.22L82.27 14.37L83.23 13.59L84.25 12.87L85.32 12.23L86.44 11.66L87.6 11.17L88.81 10.76L90.04 10.43L91.32 10.2L92.62 10.05L93.94 10L95.27 10.05L96.57 10.2Z" ></path>
	<path id="path2_id" d="M711.71 22.69L712.99 22.93L714.23 23.25L715.43 23.66L716.59 24.15L717.71 24.72L718.78 25.37L719.8 26.08L720.76 26.87L721.67 27.71L722.52 28.62L723.3 29.59L724.02 30.61L724.66 31.68L725.23 32.8L725.73 33.96L726.14 35.16L726.46 36.4L726.7 37.67L726.84 38.97L726.89 40.3L726.84 41.63L726.7 42.93L726.46 44.2L726.14 45.44L725.73 46.64L725.23 47.8L724.72 48.82L432.12 555.58L431.89 555.96L431.15 557.11L430.36 558.23L429.53 559.32L428.66 560.38L427.75 561.4L426.8 562.38L425.81 563.33L424.79 564.24L423.74 565.11L422.65 565.94L421.53 566.73L420.38 567.48L419.19 568.18L417.98 568.84L416.74 569.45L415.48 570.02L414.19 570.53L412.87 571L411.54 571.42L410.18 571.78L408.8 572.09L407.4 572.35L405.98 572.55L404.54 572.7L403.09 572.79L401.62 572.82L400.16 572.79L398.7 572.7L397.27 572.55L395.85 572.35L394.45 572.09L393.07 571.78L391.71 571.42L390.37 571L389.06 570.53L387.77 570.02L386.5 569.45L385.26 568.84L384.05 568.18L382.87 567.48L381.72 566.73L380.6 565.94L379.51 565.11L378.45 564.24L377.43 563.33L376.45 562.38L375.5 561.4L374.59 560.38L373.72 559.32L372.89 558.23L372.1 557.11L371.35 555.96L371.02 555.4L232.53 315.54L232.53 315.51L232.34 315.19L231.77 314.07L231.28 312.91L230.87 311.7L230.54 310.47L230.31 309.19L230.16 307.89L230.11 306.56L230.16 305.24L230.31 303.94L230.54 302.66L230.87 301.42L231.28 300.22L231.77 299.06L232.34 297.94L232.98 296.87L233.7 295.85L234.48 294.89L235.33 293.98L236.24 293.13L237.2 292.35L238.23 291.63L239.07 291.12L239.07 291.11L700.27 24.84L700.27 24.84L700.39 24.77L700.49 24.71L701.58 24.15L702.74 23.66L703.95 23.25L705.18 22.93L706.46 22.69L707.76 22.55L709.09 22.5L710.41 22.55L711.71 22.69Z" ></path>
	<path id="path3_id" d="M784.82 97.69L786.1 97.92L787.34 98.25L788.54 98.66L789.7 99.15L790.82 99.72L791.89 100.36L792.91 101.08L793.87 101.86L794.78 102.71L795.63 103.62L796.41 104.58L797.13 105.6L797.77 106.68L798.34 107.79L798.84 108.96L799.25 110.16L799.57 111.4L799.81 112.67L799.95 113.97L800 115.3L799.95 116.62L799.81 117.93L799.57 119.2L799.25 120.44L798.84 121.64L798.34 122.8L797.83 123.81L723.41 252.7L723.07 253.37L569.57 519.22L569.31 519.74L569.11 520.06L569.12 520.09L430.62 759.95L430.29 760.51L429.54 761.66L428.75 762.79L427.92 763.87L427.05 764.93L426.14 765.95L425.19 766.94L424.21 767.88L423.19 768.79L422.13 769.67L421.04 770.5L419.92 771.29L418.77 772.03L417.59 772.73L416.38 773.39L415.14 774.01L413.87 774.57L412.58 775.09L411.27 775.55L409.93 775.97L408.57 776.33L407.19 776.65L405.79 776.9L404.37 777.11L402.94 777.25L401.49 777.34L400.02 777.37L398.55 777.34L397.1 777.25L395.67 777.11L394.25 776.9L394.21 776.9L394.21 776.9L392.81 776.64L391.42 776.33L390.07 775.96L388.73 775.55L387.41 775.08L386.12 774.56L384.86 774L383.62 773.39L382.41 772.73L381.23 772.02L380.07 771.28L378.95 770.49L377.86 769.66L376.81 768.79L375.79 767.88L374.8 766.93L373.86 765.94L372.94 764.92L372.07 763.87L371.24 762.78L370.45 761.66L369.71 760.5L369.37 759.94L325.23 683.49L325.22 683.5L325.22 683.5L324.82 682.81L324.84 682.81L294.98 631.1L294.95 631.06L294.62 630.5L156.13 390.64L156.13 390.61L155.94 390.29L155.74 389.9L2.17 123.92L1.66 122.91L1.16 121.75L0.75 120.55L0.43 119.31L0.19 118.04L0.05 116.74L0 115.41L0.05 114.08L0.19 112.78L0.43 111.51L0.75 110.27L1.16 109.07L1.66 107.91L2.23 106.79L2.87 105.72L3.59 104.7L4.37 103.73L5.22 102.82L6.13 101.97L7.09 101.19L8.11 100.47L9.18 99.83L10.3 99.26L11.46 98.77L12.66 98.36L13.9 98.03L15.18 97.8L16.48 97.65L17.8 97.6L19.13 97.65L20.43 97.8L21.71 98.03L22.94 98.36L24.15 98.77L25.31 99.26L26.4 99.82L26.5 99.88L26.62 99.95L26.62 99.95L84.31 133.25L155.85 257.17L155.94 257.34L156.13 257.66L156.13 257.69L158.89 262.48L159.08 262.59L230.43 386.16L230.69 386.68L230.89 387L230.88 387.03L353.91 600.11L354.58 601.23L355.7 602.96L356.89 604.64L358.13 606.28L359.44 607.86L360.8 609.39L362.23 610.87L363.7 612.29L365.24 613.66L366.82 614.96L368.45 616.21L370.13 617.39L371.86 618.51L373.63 619.57L375.45 620.55L377.31 621.47L379.21 622.32L381.14 623.1L383.11 623.8L385.12 624.42L387.16 624.97L389.23 625.43L391.33 625.82L393.46 626.12L395.61 626.34L397.79 626.48L399.99 626.52L402.19 626.48L404.37 626.34L406.52 626.12L408.65 625.82L410.75 625.43L412.82 624.97L414.86 624.42L416.86 623.8L418.84 623.1L420.77 622.32L422.67 621.47L424.53 620.55L426.34 619.57L428.12 618.51L429.84 617.39L431.53 616.21L433.16 614.96L434.74 613.66L436.27 612.29L437.75 610.87L439.17 609.39L440.54 607.86L441.84 606.28L443.09 604.64L444.27 602.96L445.4 601.23L446.16 599.95L446.18 599.95L451.73 590.34L474.77 550.43L474.77 550.43L475.16 549.75L475.16 549.75L504.99 498.09L505.02 498.04L569.12 387.02L569.11 386.99L569.31 386.67L569.5 386.29L640.92 262.59L641 262.55L643.87 257.57L643.87 257.55L644.06 257.22L644.15 257.06L715.69 133.14L773.38 99.83L773.38 99.84L773.53 99.74L773.59 99.71L774.69 99.15L775.85 98.66L777.06 98.25L778.29 97.92L779.57 97.69L780.87 97.54L782.2 97.49L783.52 97.54L784.82 97.69Z" ></path></defs><g><g><g><use xlink:href="#path2_id" opacity="1" fill="#e52d2a" fill-opacity="1"></use></g><g><use xlink:href="#path3_id" opacity="1" fill="#013fcb" fill-opacity="1"></use></g><g><use xlink:href="#path1_id" opacity="1" fill="#e52d2a" fill-opacity="1"></use></g></g></g>
	</svg>

Trong nội dung tệp SVG, mình chèn thêm đoạn code CSS trong thẻ <style>. Mặc định SVG với các path ID: #path1_id, #path2_id#path3_id sẽ được đổ màu bình thường. Trong trường hợp phát hiện Dark Mode thì các path này sẽ được đổ màu trắng. Các bạn có thể thấy sự khác biệt ở hình minh họa bên dưới khi mở cùng 1 file SVG bởi 2 trình duyệt khác nhau (có Dark mode và không).

Ví dụ SVG favicon khi bật Dark Mode và không
Ví dụ SVG favicon khi bật Dark Mode và không

Các bạn chỉ cần áp dụng CSS tương tự với Favicon của mình là được.

Áp dụng Dark Mode favicon bằng javascript

Trong trường hợp các bạn không sử dụng SVG làm favicon thì hãy áp dụng phương pháp thay thế dark mode favicon bằng Javascript.

Các bạn hãy chèn đoạn mã sau vào trước thẻ đóng </body>.

<script>
var darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
handleDarkmode(darkModeMediaQuery);
function handleDarkmode(e){
	var darkModeOn = e.matches; // true if dark mode is enabled
	var favicon = document.querySelector('link[rel="shortcut icon"]'); // get favicon.ico element
	var favicon32 = document.querySelector('link[sizes="32x32"]'); // get favicon-32 element
	var favicon16 = document.querySelector('link[sizes="16x16"]'); // get favicon-16 element
	if(!favicon){
		return; // where are our favicon elements???
	}
	// replace favicons with dark/light themes
	if(darkModeOn){
		favicon.href = '/favicon-dark.ico';
		favicon32.href = '/favicon-dark-32x32.png';
		favicon16.href = '/favicon-dark-16x16.png';
	}else{
		favicon.href = '/favicon.ico';
		favicon32.href = '/favicon-32x32.png';
		favicon16.href = '/favicon-16x16.png';
	}
}
darkModeMediaQuery.addListener(handleDarkmode);
</script>

Trong đoạn mã Javascript ở trên sử dụng matchMedia để kiểm tra giá trị của CSS media query prefers-color-scheme.

Sau đó, trong hàm handleDarkmode() sử dụng querySelector để chọn đối tượng CSS favicon cần xử lý. Ở đây các bạn có thể tùy biến thêm nếu sử dụng nhiều kích thước favicon khác nhau hoặc với các trường theme-color, apple-touch-icon, … theo sở thích.

Cuối cùng, trong đoạn script trên thêm hàm handleDarkmode() vào Listener để theo dõi mỗi khi user thay đổi dark mode, script sẽ tự động cập favicon tương ứng.

Các bạn có thể tham khảo demo tại: https://vietrick.com/apps/

Kết luận

Cả 2 phương pháp trên đều có ưu nhược điểm khác nhau. Các bạn có thể linh hoạt vận dụng tùy vào tình huống của mình. Trong đó:

  • Phương pháp SVG tương đối đơn giản, hầu như không như không ảnh hưởng đến hiệu năng. Tuy nhiên, phương pháp này có yếu điểm là hiện tại các trình duyệt hỗ trợ SVG favicon còn chưa phổ biến. Tuy nhiên điều này sẽ được cải thiện dần trong tương lai không xa.
  • Phương pháp sử dụng Javascript thì linh hoạt và độ tuỳ biến cao hơn. Tuy nhiên phương pháp này sẽ ảnh hưởng một chút đến hiệu năng trang web của bạn.

Hy vọng với thủ thuật nho nhỏ này giúp ích các bạn trong quá trình thiết kế trang web của mình. Nếu có ý kiến, hãy để lại bình luận cho mình nhé.

Một số thắc mắc thường gặp

Làm gì khi SVG favicon chưa được các trình duyệt hỗ trợ phổ biến?

Bạn hoàn toàn có thể convert favicon từ định dạng.svg sang .ico, .png và các định dạng ảnh khác để sử dụng.
Bạn có thể tham khảo công cụ có sẵn tại: https://realfavicongenerator.net/

Trang web của mình cũng có hỗ trợ Dark Mode, làm sao để tự động chuyển sang chế độ Dark Mode ?

Nếu trang web của bạn có hỗ trợ chế độ Dark Mode, bạn hoàn toàn có thể sử dụng Javascript ở phương pháp thứ 2 để phát hiện và tự kích hoạt chế độ Dark Mode trên trang của bạn.

Thêm Javascript có ảnh hưởng gì đến trang web của mình không ?

Tất nhiên là khi bạn thêm càng nhiều thành phần vào thì sẽ ảnh hưởng đến hiệu năng của trang web.
Nhưng hãy yên tâm vì những đoạn script trên hoàn toàn rất nhỏ nhẹ, sẽ không ảnh hưởng đến hiệu năng và các chức năng khác trên trang.
Ngoài ra bạn cũng có thể áp dụng kỹ thuật defer Javascript để tối ưu hiệu năng.

4.8/5 - (26 votes)
Subscribe
Notify of
guest

1 Comment
Mới nhất
Cũ nhất Most Voted
Inline Feedbacks
Xem tất cả bình luận
NAD
NAD
09/07/2020 11:32

Good!