Regular text and different texts over the image in light and dark mode in WebViewer using CSS in a HTML file?

Hi,

I've been trying to do this for several weeks without success.
My goal is to display the content of an HTML file in WebViewer. This content consists of text, images, and text placed on the images. But this should work in both light and dark mode (i.e., if the phone is in either light or dark mode).

I would achieve this goal using CSS.

I have uploaded the .aia file of my project here, which contains the HTML file and the image.

Also I have uploaded two screenshots from my phone.

What I haven't been able to do so far is this. I want the text that I display in the image to be black in both light and dark mode. Instead, the text turns white in dark mode, so the white text on the light background of the image is not readable.

Is this goal even achievable using CSS?

InWebViewerTextsOverImage.aia (23.8 KB)

Any advice would be appreciated!
Regards, Paul

I don't believe you can do this:

	 /* For dark mode */
	 @media (prefers-color-scheme: dark) {
	     .text01-over-image,
	     .text02-over-image,
	     .text03-over-image,
	     {
		 color: black; /* Change text color to black. */
	     }
	 }

You will need to be more explicit in your media query:

	 /* For dark mode */
	 @media (prefers-color-scheme: dark) {
	 .text01-over-image { 
	         position: absolute;
             top: 45px;
             left: 40px;
             font-size: 22px;
             font-weight: bold;
             color: black;
	 }
	.text02-over-image { 
	         position: absolute;
             top: 132px; 
             left: 40px;
             font-size: 14px;
             font-weight: normal;
             color: black;
         }
	 .text03-over-image { 
	         position: absolute;
             top: 275px; 
             left: 70px; 
             font-size: 18px;
	         font-weight: bold;
             color: black;
         }
	 }

Personally, I would also not use an image for the background for these texts, it should be much easier to create this layout with html/css.

1 Like

I understand, but the image, on which I would place text, would explain something, would depict something that can only be best depicted in the form of an image. Of course, some well-placed text on the image is also needed for a complete explanation. I will try the code you sent later.

This picture here is just an empty illustration that doesn't depict anything, it just shows the essence of my problem.

<!DOCTYPE html>
<html lang="en">
    <head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

	<style>

	 /* Style of the whole page */
	 body, html {
	     margin: 5px;
	     padding: 2px;
	     justify-content: center;
	     align-items: center;
	     min-height: 100vh;
	     background-color: #f0f0f0;
	     color: black;
	 }


	 /* Image container - FIXED SIZE */
         .image-container {
	     position: relative;
	     width: 600px; /* This is the actual width of the image. */
	     height: 328px; /* This is the actual height of the image. */
	     overflow: hidden; /* If anything sticks out, don't let it be visible. */
	 }

	 /* The picture itself */
	 .image-container img {
	     display: block;
	     width: 600px;
	     height: 328px;
	     object-fit: contain;
	 }


	 /* For dark mode */
	 @media (prefers-color-scheme: dark) {
	     .text01-over-image { /* THIS IS THE 1ST TEXT IN THE IMAGE. */
		 position: absolute;
		 top: 45px;
		 left: 40px;
		 font-size: 22px;
		 font-weight: bold;
		 color: black;
	     }
	     .text02-over-image { /* This is the 2nd text in the image. */
		 position: absolute;
		 top: 132px;
		 left: 40px;
		 font-size: 14px;
		 font-weight: normal;
		 color: black;
	     }
	     .text03-over-image { /* THIS IS THE 3RD TEXT IN THE IMAGE. */
		 position: absolute;
		 top: 275px;
		 left: 70px;
		 font-size: 18px;
	         font-weight: bold;
		 color: black;
	     }
	 }

	 /* For light mode */
	 @media (prefers-color-scheme: light) {
	     .text01-over-image { /* THIS IS THE 1ST TEXT IN THE IMAGE. */
		 position: absolute;
		 top: 45px;
		 left: 40px;
		 font-size: 22px;
		 font-weight: bold;
		 color: black;
	     }
	     .text02-over-image { /* This is the 2nd text in the image. */
		 position: absolute;
		 top: 132px;
		 left: 40px;
		 font-size: 14px;
		 font-weight: normal;
		 color: black;
	     }
	     .text03-over-image { /* THIS IS THE 3RD TEXT IN THE IMAGE. */
		 position: absolute;
		 top: 275px;
		 left: 70px;
		 font-size: 18px;
	         font-weight: bold;
		 color: black;
	     }
	 }

	</style>
    </head>
    <body>
	<h1>Regular text and different texts over the image in light and dark mode </h1>
	<h2>Lorem Ipsum</h2>
	<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi cursus, nibh in pellentesque
	    eleifend, nunc erat accumsan leo, at ornare quam ipsum vel risus. Nunc
	    lacinia augue id odio fermentum, vel porttitor lectus porta. Nunc auctor
	    dolor nisl, et egestas elit congue eu. Morbi venenatis nunc diam, eget
	    laoreet mi lacinia at. Aliquam rhoncus dapibus eros. Duis lobortis ex
	    rhoncus sapien rhoncus, sit amet tempor purus rutrum. Donec fringilla
	    ultricies commodo. Aenean nunc libero, sollicitudin id sapien ut, ornare
	    pulvinar dui. Quisque lobortis, ligula quis imperdiet dapibus, erat dui
	    luctus justo, non malesuada enim augue vel arcu. </p>
	<div
	    class="image-container"> <img src="DifferentTextsOverImage.png" alt="The image.">
	    <div class="text01-over-image">THIS IS THE 1ST TEXT OVER THE IMAGE.</div>
	    <div class="text02-over-image">This is the 2nd text over the image.</div>
	    <div class="text03-over-image">THIS IS THE 3RD TEXT OVER THE IMAGE.</div>
	</div>
	<p>Mauris non mi orci. Nullam id suscipit lectus. Ut ultricies dignissim placerat. Suspendisse scelerisque mi risus. Vestibulum
	    nec ante quis enim convallis ornare ac a est. Suspendisse posuere augue dui,
	    nec condimentum quam ultrices a. Morbi imperdiet sem vitae magna
	    sollicitudin bibendum. Donec vel varius enim, eu efficitur arcu. Fusce eget
	    nibh nibh. Mauris quis dui eget leo dictum ullamcorper. Nunc ipsum justo,
	    tincidunt vel dui ultricies, rhoncus tincidunt urna. Mauris sit amet euismod
	    nunc. Suspendisse ullamcorper quis neque aliquet interdum. Cras vestibulum
	    lacus eu bibendum elementum. Aliquam ac mattis nunc, in rhoncus tellus. </p>
    </body>
</html>

Unfortunately, this did not work and did not solve my problem.

Ah, I didn't test in the webviewer, just my default browser on my phone.

Not sure if/how the native webviewer picks up mode of the device...

I think that this is the problem.

I guess the only thing you can do is offer dark or light mode in your html for the user to choose from.

I have found that if you set the app theme to Dark, then the webview picks up the dark theme and sets the html accordingly.

Unfortunately, setting the Dark theme can only be done at developer level.

Also:

and

CSS Dark Mode

To implement dark mode in CSS, you primarily use **CSS custom properties** (variables) combined with the **`prefers-color-scheme` media query** to detect the user's system preference.

Here is the standard approach:

1.  **Define default (light mode) variables** in the `:root` selector.
2.  **Override variables** inside a `@media (prefers-color-scheme: dark)` block.
3.  **Apply variables** to your elements using the `var()` function.

```css
/* 1. Define default light mode colors */
:root {
  --bg-color: #ffffff;
  --text-color: #000000;
}

/* 2. Override for dark mode preference */
@media (prefers-color-scheme: dark) {
  :root {
    --bg-color: #121212;
    --text-color: #ffffff;
  }
}

/* 3. Apply to elements */
body {
  background-color: var(--bg-color);
  color: var(--text-color);
}

For manual toggling without JavaScript, you can use hidden checkboxes and sibling selectors to change the variable values based on the checked state. Alternatively, newer browsers support the light-dark() CSS function, which allows you to specify different values for light and dark themes directly within a single property declaration:

:root {
  color-scheme: light dark;
}

body {
  background-color: light-dark(#ffffff, #121212);
  color: light-dark(#000000, #ffffff);
}

To ensure user agents (like form controls and scrollbars) respect your theme, set the color-scheme property on the root element.

1 Like

I have done a bit of work, and hopefully a solution for you...

  1. Added an OS light-dark theme checker to my webviewextra extension
  2. Use the above to set the webviewstring
  3. Run some javascript on load to set light/dark mode based upon the value in the webviewstring

example html file

<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
body { background-color:white;   color:black }
h1 { color: black; }
</style>
<body>
<div>
 <h1>This is a Heading</h1>
 <p>This is a paragraph.</p>
 <p>This is another paragraph.</p>
</div>
<script>
if (AppInventor){
if (window.AppInventor.getWebViewString() == "true") {
document.body.style.color='white';
document.body.style.backgroundColor='black';
const headings = document.querySelectorAll("h1");
headings.forEach(h1 => { h1.style.color = "red";});
}
else {
document.body.style.color='black';
document.body.style.backgroundColor='white';
const headings = document.querySelectorAll("h1");
headings.forEach(h1 => { h1.style.color = "black";});
}
}
</script>
</body>
</html>

Blocks

Extension to test:
webviewextra

1 Like

I tried, but unfortunately it doesn't work on my phone.
In my phone's settings, if I change the light mode to dark, or vice versa, my app doesn't respond, and the text on the image remains black in light mode, and white in dark mode (which is unreadable on the light surface of the image).

<!DOCTYPE html>
<html lang="en">
    <head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"><!-- , user-scalable=no"> -->

	<style>

	 /* Style of the whole page */
	 body, html {
	     margin: 5px;
	     padding: 2px;
	     justify-content: center;
	     align-items: center;
	     min-height: 100vh;
	     /*background-color: #f0f0f0;*/
	     /*color: black;*/
	 }

	 /* Image container - FIXED SIZE */
         .image-container {
	     position: relative;
	     width: 600px; /* This is the actual width of the image. */
	     height: 328px; /* This is the actual height of the image. */
	     overflow: hidden; /* If anything sticks out, don't let it be visible. */
	 }

	 /* The picture itself */
	 .image-container img {
	     display: block;
	     width: 600px;
	     height: 328px;
	     object-fit: contain;
	 }

	 .text01-over-image { /* THIS IS THE 1ST TEXT IN THE IMAGE. */
	     position: absolute;
	     top: 45px;
	     left: 40px;
	     font-size: 22px;
	     font-weight: bold;
	 }
	 .text02-over-image { /* This is the 2nd text in the image. */
	     position: absolute;
	     top: 132px;
	     left: 40px;
	     font-size: 14px;
	     font-weight: normal;
	 }
	 .text03-over-image { /* THIS IS THE 3RD TEXT IN THE IMAGE. */
	     position: absolute;
	     top: 275px;
	     left: 70px;
	     font-size: 18px;
	     font-weight: bold;
	 }

	</style>
    </head>
    <body>
	<script>
	 if (AppInventor){
	     if (window.AppInventor.getWebViewString() == "true") {
		 document.querySelectorAll('.text01-over-image, .text02-over-image, .text03-over-image')
			 .forEach(e => e.style.color = 'orange');
	     }
	     else {
		 document.querySelectorAll('.text01-over-image, .text02-over-image, .text03-over-image')
			 .forEach(e => e.style.color = 'green');
	     }
	 }
	</script>
	<h1>Regular text and different texts over the image in light and dark mode </h1>
	<h2>Lorem Ipsum</h2>
	<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi cursus, nibh in pellentesque
	    eleifend, nunc erat accumsan leo, at ornare quam ipsum vel risus. Nunc
	    lacinia augue id odio fermentum, vel porttitor lectus porta. Nunc auctor
	    dolor nisl, et egestas elit congue eu. Morbi venenatis nunc diam, eget
	    laoreet mi lacinia at. Aliquam rhoncus dapibus eros. Duis lobortis ex
	    rhoncus sapien rhoncus, sit amet tempor purus rutrum. Donec fringilla
	    ultricies commodo. Aenean nunc libero, sollicitudin id sapien ut, ornare
	    pulvinar dui. Quisque lobortis, ligula quis imperdiet dapibus, erat dui
	    luctus justo, non malesuada enim augue vel arcu. </p>
	<div
	    class="image-container"> <img src="DifferentTextsOverImage.png" alt="The image.">
	    <div class="text01-over-image">THIS IS THE 1ST TEXT OVER THE IMAGE.</div>
	    <div class="text02-over-image">This is the 2nd text over the image.</div>
	    <div class="text03-over-image">THIS IS THE 3RD TEXT OVER THE IMAGE.</div>
	</div>
	<p>Mauris non mi orci. Nullam id suscipit lectus. Ut ultricies dignissim placerat. Suspendisse scelerisque mi risus. Vestibulum
	    nec ante quis enim convallis ornare ac a est. Suspendisse posuere augue dui,
	    nec condimentum quam ultrices a. Morbi imperdiet sem vitae magna
	    sollicitudin bibendum. Donec vel varius enim, eu efficitur arcu. Fusce eget
	    nibh nibh. Mauris quis dui eget leo dictum ullamcorper. Nunc ipsum justo,
	    tincidunt vel dui ultricies, rhoncus tincidunt urna. Mauris sit amet euismod
	    nunc. Suspendisse ullamcorper quis neque aliquet interdum. Cras vestibulum
	    lacus eu bibendum elementum. Aliquam ac mattis nunc, in rhoncus tellus. </p>
    </body>
</html>


Where am I wrong?
I am attaching the .aia file of my project.
InWebViewerTextsOverImage.aia (50.5 KB)

Did you also try my html?

I tried your html file only as an html file on my phone, i.e. I opened it in both light and dark mode, and of course the text is black in light mode and white in dark mode. However, I haven't integrated your html file into the Appinventor project yet. I will do that tomorrow.

I have included your html file in this project, installed it on my phone, and tested how the text appears when I switch between light and dark modes on my phone.
Yes, your html file works fine (see the two screenshots attached).



Okay, I changed the title color a little.
I'm also attaching the code for the html file:

<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
body { background-color:white;   color:black }
h1 { color: green; }
</style>
<body>
<div>
 <h1>This is a Heading</h1>
 <p>This is a paragraph.</p>
 <p>This is another paragraph.</p>
</div>
<script>
if (AppInventor){
if (window.AppInventor.getWebViewString() == "true") {
document.body.style.color='white';
document.body.style.backgroundColor='black';
const headings = document.querySelectorAll("h1");
headings.forEach(h1 => { h1.style.color = "red";});
}
else {
document.body.style.color='black';
document.body.style.backgroundColor='white';
const headings = document.querySelectorAll("h1");
headings.forEach(h1 => { h1.style.color = "green";});
}
}
</script>
</body>
</html>

InWebViewerTextsOverImage.aia (51.0 KB)


So, my html file should work too, but there might be something wrong with it, as I haven't been able to color the text to be placed on the image according to the light and dark modes yet.

Do you have any advice regarding my html file? What could be wrong with it that it doesn't change the color of the text placed on the image according to the light and dark modes?

I will have to take a look later today, busy cleaning out a years dust and fluff from my computer!

2 Likes

Your webviewstring is set only in the screen1.initialize so after changing light/dark mode you have to refresh the whole page

Your script needs to be at the end of the (but still inside the) tag after all the text, otherwise your texts and their classes have not been initialised.

1 Like

This does not work with black. The black color does not remain black, but turns white (over the white surface of the background image), even though I set it in the html file using css and javascript so that the text remains black even in dark mode (because this is how the text becomes visible over a white or light-colored background. As the two screenshots attached show, it works with red and green colors, but not with black. I also tried other dark colors, such as the color 'navy', which did not show navy in dark mode, but a very pale pink.

Why doesn't this method work with black, navy, or maybe other dark colors?


Please share your most recent html file again.

<!DOCTYPE html>
<html lang="en">
    <head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"><!-- , user-scalable=no"> -->

	<style>

	 /* Style of the whole page */
	 body, html {
	     margin: 5px;
	     padding: 2px;
	     justify-content: center;
	     align-items: center;
	     min-height: 100vh;
	     /*background-color: #f0f0f0;*/
	     /*color: black;*/
	 }

	 /* Image container - FIXED SIZE */
         .image-container {
	     position: relative;
	     width: 600px; /* This is the actual width of the image. */
	     height: 328px; /* This is the actual height of the image. */
	     overflow: hidden; /* If anything sticks out, don't let it be visible. */
	 }

	 /* The picture itself */
	 .image-container img {
	     display: block;
	     width: 600px;
	     height: 328px;
	     object-fit: contain;
	 }

	 .text01-over-image { /* THIS IS THE 1ST TEXT OVER THE IMAGE. */
	     position: absolute;
	     top: 45px;
	     left: 40px;
	     font-size: 22px;
	     font-weight: bold;
	 }
	 .text02-over-image { /* This is the 2nd text over the image. */
	     position: absolute;
	     top: 132px;
	     left: 40px;
	     font-size: 14px;
	     font-weight: normal;
	 }
	 .text03-over-image { /* THIS IS THE 3RD TEXT OVER THE IMAGE. */
	     position: absolute;
	     top: 275px;
	     left: 70px;
	     font-size: 18px;
	     font-weight: bold;
	 }

	</style>
    </head>
    <body>
	<h1>Regular text and different texts over the image in light and dark mode </h1>
	<h2>Lorem Ipsum</h2>
	<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi cursus, nibh in pellentesque
	    eleifend, nunc erat accumsan leo, at ornare quam ipsum vel risus. Nunc
	    lacinia augue id odio fermentum, vel porttitor lectus porta. Nunc auctor
	    dolor nisl, et egestas elit congue eu. Morbi venenatis nunc diam, eget
	    laoreet mi lacinia at. Aliquam rhoncus dapibus eros. Duis lobortis ex
	    rhoncus sapien rhoncus, sit amet tempor purus rutrum. Donec fringilla
	    ultricies commodo. Aenean nunc libero, sollicitudin id sapien ut, ornare
	    pulvinar dui. Quisque lobortis, ligula quis imperdiet dapibus, erat dui
	    luctus justo, non malesuada enim augue vel arcu. </p>
	<div
	    class="image-container"> <img src="DifferentTextsOverImage.png" alt="The image.">
	    <div class="text01-over-image">THIS IS THE 1ST TEXT OVER THE IMAGE.</div>
	    <div class="text02-over-image">This is the 2nd text over the image.</div>
	    <div class="text03-over-image">THIS IS THE 3RD TEXT OVER THE IMAGE.</div>
	</div>

	<script>
	 if (AppInventor){
	     if (window.AppInventor.getWebViewString() == "true") {
		 document.querySelectorAll('.text01-over-image, .text02-over-image')
			 .forEach(e => e.style.color = 'red');
		 document.querySelectorAll('.text03-over-image')
			 .forEach(e => e.style.color = 'black');
		 document.body.style.color='blue';
	     }
	     else {
		 document.querySelectorAll('.text01-over-image, .text02-over-image')
			 .forEach(e => e.style.color = 'green');
		 document.querySelectorAll('.text03-over-image')
			 .forEach(e => e.style.color = 'black');
		 document.body.style.color='orange';
	     }
	 }
	</script>
    </body>
</html>

Do you want to colour text03 differently to the other two, or is that just for testing?