Introspecting CSS via the CSS OM: Getting supported properties, shorthands, longhands

栏目: IT技术 · 发布时间: 4年前

内容简介:ForThere are essentially two steps for this:I decided to tell this story in the inverse order. In my exploration, I first focused on figuring out shorthands (2), because I had coded getting a list of properties many times before, but since (1) is useful in

For some of the statistics we are going to study for this year’s Web Almanac we may end up needing a list of CSS shorthands and their longhands. Now this is typically done by maintaining a data structure by hand or guessing based on property name structure . But I knew that if we were going to do it by hand, it’s very easy to miss a few of the less popular ones, and the naming rule where shorthands are a prefix of their longhands has failed to get standardized and now has even more exceptions than it used to. And even if we do an incredibly thorough job, next year the data structure will be inaccurate, because CSS and its implementations evolve fast. The browser knows what the shorthands are, surely we should be able to get the information from it… right?

There are essentially two steps for this:

  1. Get a list of all CSS properties
  2. Figure out how to test if a given property is a shorthand and how to get its longhands if so.

I decided to tell this story in the inverse order. In my exploration, I first focused on figuring out shorthands (2), because I had coded getting a list of properties many times before, but since (1) is useful in its own right (and probably in more use cases), I felt it makes more sense to examine that first.

Note:I’m using document.body instead of a dummy element in these examples, because I like to experiment in about:blank , and it’s just there and because this way you can just copy stuff to the console and try it wherever, even right here while reading this post. However, if you use this as part of code that runs on a real website, it goes without saying that you should create and test things on a dummy element instead!

Getting a list of all CSS properties from the browser

In Chrome and Safari, this is as simple as Object.getOwnPropertyNames(document.body.style) . However, in Firefox, this doesn’t work. Why is that? To understand this (and how to work around it), we need to dig a bit deeper.

In Chrome and Safari, element.style is a CSSStyleDeclaration instance. In Firefox however, it is a CSS2Properties instance, which inherits from CSSStyleDeclaration . CSS2Properties is an older interface, defined in the DOM 2 Specification , which is now obsolete. In the current relevant specification , CSS2Properties is gone, and has been merged with CSSStyleDeclaration . However, Firefox hasn’t caught up yet .

Introspecting CSS via the CSS OM: Getting supported properties, shorthands, longhands
Firefox on the left, Safari on the right. Chrome behaves like Safari.

Since the properties are on CSSStyleDeclaration , they are not own properties of element.style , so Object.getOwnPropertyNames() fails to return them. However, we can extract the CSSStyleDeclaration instance by using __proto__ or Object.getPrototypeOf() , and then Object.getOwnPropertyNames(Object.getPrototypeOf(document.body.style)) gives us what we want!

So we can combine the two to get a list of properties regardless of browser:

let properties = Object.getOwnPropertyNames(
	style.hasOwnProperty("background")? 
	style : style.__proto__
);

And then, we just drop non-properties, and de-camelCase:

properties = properties.filter(p => style[p] === "") // drop functions etc
	.map(prop => { // de-camelCase
		prop = prop.replace(/[A-Z]/g, function($0) { return '-' + $0.toLowerCase() });

		if (prop.indexOf("webkit-") > -1) {
			prop = "-" + prop;
		}

		return prop;
	});

You can see a codepen with the result here :

Testing if a property is a shorthand and getting a list of longhands

The main things to note are:

  • When you set a shorthand on an element’s inline style, you are essentially setting all its longhands.
  • element.style is actually array-like, with numerical properties and .length that gives you the number of properties set on it. This means you can use the spread operator on it:
> document.body.style.background = "red";
> [...document.body.style] 
< [
	"background-image", 
	"background-position-x", 
	"background-position-y", 
	"background-size", 
	"background-repeat-x", 
	"background-repeat-y", 
	"background-attachment", 
	"background-origin", 
	"background-clip", 
	"background-color"
]

Interestingly, document.body.style.cssText serializes to background: red and not all the longhands.

There is one exception: The all property . In Chrome, it does not quite behave as a shorthand:

> document.body.style.all = "inherit";
> [...document.body.style]
< ["all"]

Whereas in Safari and Firefox, it actually returns every single property that is not a shorthand !

Introspecting CSS via the CSS OM: Getting supported properties, shorthands, longhands
Firefox and Safari expand all to literally all non-shorthand properties.

While this is interesting from a trivia point of view, it doesn’t actually matter for our use case, since we don’t typically care about all when constructing a list of shorthands, and if we do we can always add or remove it manually.

So, to recap, we can easily get the longhands of a given shorthand:

function getLonghands(property) {
	let style = document.body.style;
	style[property] = "inherit"; // a value that works in every property
	let ret = [...style];
	style.cssText = ""; // clean up
	return ret;
}

Putting the pieces together

You can see how all the pieces fit together (and the output!) in this codepen :

How many of these shorthands did you already know?

Part 2: Building a CSS custom property dependency tree for the current page?

Next week, I may write a Part 2 about building a custom property dependency tree for the current page, which is what I’m currently working on. Stay tuned!


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

移动的帝国

移动的帝国

曾航、刘羽、陶旭骏 / 浙江大学出版社 / 2014-1-1 / 48.00

日本是全世界移动互联网最发达的国家之一,堪称移动的帝国。在手机游戏、手机支付、移动医疗、移动电子商务、手机电视等方面,日本都充当了全球移动互联网的试验田。 曾经傲视全球的日本运营商将怎样面对转型的挑战?iPhone来势汹汹,如何打破封闭的日本移动互联网体系?日本在智能手机时代的手机游戏、O2O、移动医疗、移动广告等方面,涌现出了哪些值得借鉴的商业模式? 本书作者团队先后数次前往日本调研......一起来看看 《移动的帝国》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

MD5 加密
MD5 加密

MD5 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器