Since this question was answered, the HTML Preview feature was deprecated in favor of the Webview. Here is the relevant part of the documentation: Theming Webview content.
Vlad's answer is still valid, but I found it incomplete.
The style sheet of the custom html content within your Webview indeed needs to be taking the document.body.class
into account, but besides just reading the attribute value when the page is loaded, you also need to handle the events, when the user changes the theme after your Webview has already been loaded. So Vald's answer was helpful, but I realized I need to handle the dynamic theme change case. It usually happens, when I am presenting on the big screen and people ask me to switch the theme for clarity and then I am stuck with the Webview that is theme-confused and illegible.
Here is what helped:
The html code needs to trigger a onLoad()
javascript function when it is done loading, and it should assume a default theme (so the HTML is testable outside of the Webview).
<body onload="onLoad()" class="vscode-light">
Then the javascript onLoad()
function needs to read the initial value of document.body.className
as well as subscribe to subsequent changes using the MutationObserver
.
var theme = 'unknown';
function onLoad() {
postCommand('onload');
applyTheme(document.body.className);
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutationRecord) {
applyTheme(mutationRecord.target.className);
});
});
var target = document.body;
observer.observe(target, { attributes : true, attributeFilter : ['class'] });
}
function applyTheme(newTheme) {
var prefix = 'vscode-';
if (newTheme.startsWith(prefix)) {
// strip prefix
newTheme = newTheme.substr(prefix.length);
}
if (newTheme === 'high-contrast') {
newTheme = 'dark'; // the high-contrast theme seems to be an extreme case of the dark theme
}
if (theme === newTheme) return;
theme = newTheme;
console.log('Applying theme: ' + newTheme);
/* PUT YOUR CUSTOM CODE HERE */
}