如何以编程方式启用"-ms-high-contrast"媒体查询?



我想在我的网站上启用高对比度模式,并将所有与可访问性相关的规则放入高对比度媒体查询中:

@media screen and (-ms-high-contrast: active) {
/* All high contrast styling rules */
}

但是,如何在JavaScript中以编程方式启用这种模式?我想给我的用户一个按钮,让他们根据自己的意愿切换这个功能。有可能吗?我做得对吗?也许有更好的解决方案。

感谢您的帮助。

由于媒体查询是自动的(基于浏览器条件),您需要在CSS中模拟该块,但根据用户交互应用和删除它。

在我看来,你应该简单地编写样式来模仿IE的高对比度模式,然后在点击按钮时在文档(可能是正文)上切换一个类。

把你的新类和子定义放在CSS的底部,这样你就知道它们会覆盖以前的属性。

例如:

h2 {
font-size: 14px;
color: #dddddd;
}
/* overrides a normal h2 when highContrast class is added to the body */
/* use a post processor (LESS/SCSS) to easily nest elements */
body.highContrast h2 {
font-size: 18px;
color: #000;
font-weight: bold;
}

这是一种非常简单的技术:使用-ms高对比度创建一个媒体查询,在其中放置IE 10和11特定的CSS样式。由于-ms高对比度是Microsoft特有的(并且仅在IE 10+中可用),因此它只能在Internet Explorer 10及更高版本中解析。

-ms高对比度支持两个值:none和active。因此,无论属性设置如何,都要以IE10+为目标,请使用以下媒体查询:

@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { /* IE10+ CSS styles go here */

定义要为ms高对比度模式添加的类。

一旦用户单击该按钮,就必须动态地将相关类添加到dom元素中。

注意:这只适用于IE10+浏览器。

请注意如果您想从浏览器启用高对比度模式,则不能。这个答案是如何通过点击按钮应用高对比度样式,同时保持不依赖JavaScript的媒体查询。

此解决方案允许您将IE的样式保留为媒体查询,但也允许手动切换它们。它确实取决于你的高对比度CSS是否位于一个单独的外部文件中。

我们所做的是将包含高对比度CSS规则的样式表添加为外部文件。

我们给这个文件一个唯一的ID(#doNotChangeMe)和相关的媒体查询media="screen and (-ms-high-contrast: active)"

由于以上文件只适用于IE,我们可以放心地将其单独使用。

然后,我们创建一个函数,该函数还可以在单击按钮时添加和删除此样式表。

我创建了一个简单的toggle函数,它将使用CSS选择器查询样式表是否存在(没有#doNotChangeMeid)。

'link[href*="' + externalFileName + '"]:not(#doNotChangeMe)'(查找与我们提供的href的链接,只要它没有相关的ID)。

然后,我们看看这个CSS文件是否存在于DOM中,如果不存在,我们会再次添加它(假设你的高对比度CSS是DOM中的最后一个样式表,这不会造成任何伤害),否则我们会将其删除。

我确实试图通过程序化地更改媒体查询来使其更干净,但这在浏览器中的结果似乎喜忧参半,而且以上操作似乎一致(例如,如果您尝试更改media.mediaText,CORS安全策略就会生效)。

我链接到示例中的Bootstrap样式表只是为了便于演示。您必须检查DOM,以查看此函数是否未触及高对比度样式表(或者在IE中启用高对比度模式,以查看切换不会影响任何内容)。

请注意我没有向切换按钮添加任何指示器来显示模式是否处于活动状态,请确保添加相关的WAI-ARIA、按钮文本等。

//Please note that the below assumes you do not want to interfere with normal media query, if you want people who do have high contrast mode enabled you will need to modify this to remove the ignoreIdOrClass part and instead have a variable containing the state.
var ignoreIdOrClass = '#doNotChangeMe'; //this is the ID of the file that was already in the DOM we do not want to touch
var externalFileName = document.querySelector(ignoreIdOrClass).href; //we grab the URL of the file we want to replicate
function toggleHighContrast() {
var linkNode = document.querySelector('link[href*="' + externalFileName + '"]:not(' + ignoreIdOrClass + ')'); //see if we have added this style sheet to the DOM ourselves, ignore the one with the ID we said to ignore
if(!linkNode){ //our css file copy doesn't exist so create it and add it to the document HEAD
var head = document.head;
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = externalFileName;

head.appendChild(link);
}else{ //our css copy does exist so remove it

linkNode.parentNode.removeChild(linkNode);
}
}
document.getElementById("myBtn").addEventListener("click", toggleHighContrast);
<link id="doNotChangeMe" rel="stylesheet" media="screen and (-ms-high-contrast: active)" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" />
<div style="padding: 20px;">
<button id="myBtn" class="btn btn-primary btn-lg">Toggle High Contrast</button>
</div>

正如@GrahamRitchie所指出的,虽然你不能通过JavaScript启用浏览器的高对比度设置,但你通常可以检测它是否已经启用。

对于Windows10上的大多数浏览器,您可以检测是否启用了高对比度

  1. 创建一个具有背景色的元素,

  2. 将其附加到DOM,以及

  3. 测试背景颜色是否仍然存在:

isUsingHighContrastMode = () => {
const testDiv = document.createElement('div');
testDiv.style.color = 'rgb(50, 50, 50)';
document.body.appendChild(testDiv);
const color = document.defaultView!.getComputedStyle(testDiv, null).color;
document.body.removeChild(testDiv);
return color !== 'rgb(50, 50, 50)' ? true : false;
}

Chrome有自己的高对比度扩展,通常你不需要检测它。但如果你检测到了,请检查html标签上的hc属性:

const htmlTag = document.getElementsByTagName(
'html'
)[0];
const isUsingChromeHighContrastExtension: boolean =
htmlTag.getAttribute('hc') !== null;

对于MacOS,您可以检测用户是否启用了反转颜色,如下所示:

isUsingMacInvertedColors = () => {
const mediaQueryList = window.matchMedia('(inverted-colors: inverted)');
return mediaQueryList.matches;
}

然后你就可以应用你的造型规则了!


注意:我之前疯狂地尝试检测其他MacOS的高对比度设置。这些答案让我暂时停止了尝试,尽管我希望未来能有更好的解决方案。

最新更新