30秒学会 JavaScript 片段 · 2022年7月31日

30秒学会 JavaScript 片段 – Use JavaScript to prefix a CSS property based on the browser

Sometimes, you want to use a CSS property that is not yet supported by all browsers. Browsers often support these properties by using a vendor prefix, which is a string that is prepended to the property name. For example, Safari uses -webkit-, Firefox uses -moz- etc.

But how can you detect if a browser supports a certain CSS property? And how can you prefix a CSS property based on the current browser? Luckily, the CSSStyleDeclaration interface exposes dashed and camel-cased attributes for all supported CSS properties.

In order to use this interface, you can access the style property of the Document.body object. Then, you can check if the property is defined as-is or with a vendor prefix.

代码实现

// Check if the 'appearance' property is defined
typeof document.body.style.appearance !== 'undefined';

// Check explicitly for the 'webkitAppearance' property
typeof document.body.style.webkitAppearance !== 'undefined';

This is pretty simple to check for a specific property or browser environment, but it’s a hassle to do this for multiple properties and browsers. As browser prefixes are well-known, you can use an array of prefixes to check against each one of them.

使用样例

// Known browser prefixes (empty string for the default property)
const prefixes = ['', 'webkit', 'moz', 'ms', 'o'];

Prefixed properties can be checked, using the camel-cased attribute of the CSSStyleDeclaration interface. You can use String.prototype.charAt() and String.prototype.toUpperCase() to capitalize the property name, which will be appended to the vendor prefix string.

const prop = 'appearance';
const prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1);

prefixes.map(prefix => (prefix ? prefix + capitalizedProp : prop));
// [
//  'appearance',
//  'webkitAppearance',
//  'mozAppearance',
//  'msAppearance',
//  'oAppearance'
// ]

Finally, you can use Array.prototype.findIndex() to check if Document.body has one of the prefixed properties defined in its CSSStyleDeclaration object. If it does, you can return the prefixed property, otherwise you can return null.

const prefix = prop => {
  const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1);
  const prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
  const i = prefixes.findIndex(
    prefix =>
      typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !==
      'undefined'
  );
  return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null;
};

prefix('appearance');
// 'appearance' on a supported browser, otherwise 'webkitAppearance',
//   'mozAppearance', 'msAppearance' or 'oAppearance'

翻译自:https://www.30secondsofcode.org/js/s/prefix-css-property