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

How to programmatically enable "-ms-high-contrast" media query?

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

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

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

感谢您的帮助。

技术非常简单:使用 -ms-high-contrast 创建媒体查询,在其中放置 IE 10 和 11 特定的 CSS 样式。因为 -ms-high-contrast 是微软特有的(并且只在 IE 10+ 中可用),它只会在 Internet Explorer 10 及更高版本中被解析。

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

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

定义要为 ms-high-contrast 模式添加的 类。

用户单击按钮后,您必须将相关 类 动态添加到 dom 元素。

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

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

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

将新的 class 和子定义放在 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;
}

正如@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有自己的High Contrast extension, and usually you don't need to detect it. But if you do, :

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;
}

然后您可以应用您的样式规则!


注意:我之前疯狂地尝试过 。这些答案让我暂时停止尝试,但我希望将来有更好的解决方案。

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

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

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

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

由于上述文件仅适用于 IE,因此我们可以安全地保留它。

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

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

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

然后我们查看 CSS 文件是否存在于 DOM 中,如果不存在,我们将再次添加它(假设您的高对比度 CSS 是DOM 中的最后一个样式 sheet),否则我们将其删除。

我确实尝试通过以编程方式更改媒体查询来使其更清晰,但是这似乎在浏览器中产生了不同的结果,并且上面的内容似乎始终如一地工作(如果您尝试更改,CORS 安全策略就会启动 media.mediaText 例如)。

为了便于演示,我已将示例中的 link 修改为 Bootstrap 样式 sheet。您将必须检查 DOM 以查看此功能未触及高对比度样式 sheet(或在 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>