Front-End & Daily

[JS] Sample to dynamically and smoothly change meta theme-color

[JS] Sample to dynamically and smoothly change meta theme-color

The meta tag "theme-color" that can change the browser toolbar color, mainly on smartphones.

<meta name="theme-color" content="#F0F5F9">

I will try to dynamically change this with JS.

Table of Contents

First, try changing it normally

First, I'll try changing it normally, without animation.

On devices where theme-color is effective, such as smartphones,

Please click to try it.

Change color code here.

I will omit the detailed source code, but

it's minimally like this.

//「.btn」をクリックしたとき
$(".btn").on("click", function(){
	//metaタグを書き換え
	$("meta[name=theme-color]").attr("content", "#F0F5F9");
});

How it looks on a real device

iOS16 Safari

Android12 Chrome

Both switched instantly without animation.

meta theme-color did not work in Chrome on iOS.

Try switching smoothly

I created a function that switches with a smooth animation.

Sample

Change color code here.

Sample Source

$(function(){
	const meta_theme = $("meta[name=theme-color]");

	$("input[name=theme_animate]").on("change", function(){
		let from = $("input[data-animate=animate1]").val();
		let to = $("input[data-animate=animate2]").val();
		theme_color(from, to);
	});

	//Function to switch smoothly ("#ace0f9", "#fff1eb")
	function theme_color(from, to) {
		let frames = 30; //フレーム
		let duration = 1000; //アニメーションの長さ ms

		let per = duration / frames; //1フレームあたりの長さ

		let from_rgb = convert_rgb(from);
		let to_rgb = convert_rgb(to);

		for(let i=0; i<=frames; i++){
			(function(pram) {
				setTimeout(function() {
					//それぞれの差
					let diff_r = (from_rgb[0] - to_rgb[0]) / frames * pram;
					let diff_g = (from_rgb[1] - to_rgb[1]) / frames * pram;
					let diff_b = (from_rgb[2] - to_rgb[2]) / frames * pram;

					//このフレームでの色
					let r = from_rgb[0] - diff_r;
					let g = from_rgb[1] - diff_g;
					let b = from_rgb[2] - diff_b;

					let code = convert_16([r, g, b]);

					meta_theme.attr("content", code);
				}, pram * per);
			})(i);
		}
	}

	//Function to convert hexadecimal to RGB ("#ace0f9")
	function convert_rgb(str){
		let hex_r, hex_g, hex_b;

		if (str.length < 6) {
			// #abcをa,b,cに分割
			let hex_3digit = str.match(/^#([0-9a-f]{1})([0-9a-f]{1})([0-9a-f]{1})/);
			// aa
			hex_r = hex_3digit[1] + hex_3digit[1];
			// bb
			hex_g = hex_3digit[2] + hex_3digit[2];
			// cc
			hex_b = hex_3digit[3] + hex_3digit[3];
		} else {
			// #abcdefをab,cd,efに分割
			let hex_6digit = str.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/);
			// ab
			hex_r = hex_6digit[1];
			// cd
			hex_g = hex_6digit[2];
			// ef
			hex_b = hex_6digit[3];
		}

		// 16進数から10進数へ
		let rgb_r = parseInt(hex_r, 16);
		let rgb_g = parseInt(hex_g, 16);
		let rgb_b = parseInt(hex_b, 16);

		//Return as an array
		return [rgb_r, rgb_g, rgb_b];
	}

	//Function to convert RGB to hexadecimal
	function convert_16(arr){
		//If the argument array contains a negative number, set it to 00
		for(let i=0; i<3; i++){
			if(arr[i] < 0){
				arr[i] = 0;
			}
		}

		// From decimal to hexadecimal
		let hex_r = (parseInt(arr[0])).toString(16);
		let hex_g = (parseInt(arr[1])).toString(16);
		let hex_b = (parseInt(arr[2])).toString(16);

		// Add 0 if it's a single digit
		hex_r = hex_r.replace(/(^[0-9a-f]{1}$)/, '0$1'); 
		hex_g = hex_g.replace(/(^[0-9a-f]{1}$)/, '0$1'); 
		hex_b = hex_b.replace(/(^[0-9a-f]{1}$)/, '0$1'); 

		return '#' + hex_r + hex_g + hex_b;
	}
});

How it looks on a real device

iOS16 Safari

Android12 Chrome

Both animated quite beautifully.

I referred to this article for converting RGB and hexadecimal values.

RGB and Hexadecimal Conversion | My Private Notes

Comments

  • #001

    Anonymous

    I was impressed lol

    I was in the middle of PWA development and was unsure about the theme color, so being able to test it easily was very helpful!

  • #002

    Kento Kanai

    I'm glad it was helpful!

    Thank you for your comment 😄

After reviewing the content, we will publish it, omitting personal information.

Enter your name and email address too

Please enter if you would like a reply by email.

The personal information provided will not be disclosed. It will only be used for replies.

It will be sent directly. Please confirm and "Send".

If this was helpful, we appreciate your support!
Any support received will be used for childcare.

Send support via OFUSE


Or support by buying something from the buttons below
(You don't have to buy the linked product.)

Amazon

楽天市場

Yahoo!ショッピング

PR

As an Amazon Associate, "Ken" earns from qualifying purchases.

Share

Share on Twitter Share on Facebook Share on LINE Share on Hatena Bookmark