construct-stylesheets icon indicating copy to clipboard operation
construct-stylesheets copied to clipboard

Consider a different name for 'adoptedStyleSheets'

Open Rich-Harris opened this issue 6 years ago • 55 comments

The name adoptedStyleSheets is a bit awkward, for a few reasons:

It's long

Unwieldy names aren't uncommon in the DOM, but it's particularly problematic when the most common example usage...

document.adoptedStyleSheets = [...document.adoptedStyleSheets, newSheet];

...involves repetition. (I'm hopeful that this pattern will be abandoned in favour of explicit methods, due to the fact that it will result in nasty race condition bugs, but it's still a lot to type.)

'Adopted' is confusing

I'm not aware of any other places in the DOM where this verb is used. The most commonly understood meaning of 'adopted' is in the family context, where there's a parent-child relationship. Multiple families cannot adopt the same child. Used here, it could easily be understood to mean that a stylesheet can belong to a single element.

The casing is hard to remember

Although CSS stands for Cascading Style Sheets, people informally talk about 'stylesheets' rather than 'style sheets' — one word. You only ever see <link rel="stylesheet">, never <link rel="styleSheet">. This makes it harder to remember whether it's adoptedStylesheets or adoptedStyleSheets, particularly if you're not writing it frequently.

In fact, this is part of a spec called Constructable Stylesheets!

Of course, there is an easy way to remember it, but...

...The acronym is unfortunate

Not that I'm opposed to levity in web development, but I guarantee that this will be universally shortened to 'document dot aSS' or 'this dot aSS'. I'm not sure if that's what everyone had in mind.


Is there a reason this couldn't simply be document.css? An API like this would be a lot more palatable to most developers:

document.css.add(sheet);

(I realise there are concerns about being able to control the order of the collection, so add and remove may be too simplistic an API, but I'd expect appending to account for 99% of cases. Regardless, that's a separate issue.)

Rich-Harris avatar Aug 14 '19 12:08 Rich-Harris

I like it.

It mimics the KISS paradigm of :

e.classList.add('...')

... which I love to use.


In webcomponents, I probably would like to do :

this.css.add(sheet);

To add global stylesheets, I might do :

globalThis.css.add(sheet);

dtruffaut avatar Aug 14 '19 12:08 dtruffaut

'Adopted' is confusing I'm not aware of any other places in the DOM where this verb is used.

It's defined here and can be seen in a few APIs such as document.adoptNode and the CE callback adoptedCallback.

matthewp avatar Aug 14 '19 12:08 matthewp

Step 2 from that spec page:

If node’s parent is not null, remove node from its parent.

In other words, a node cannot be adopted by multiple parents. It feels like it's being used incorrectly here.

Rich-Harris avatar Aug 14 '19 12:08 Rich-Harris

There is a namespace object named CSS, though I think it's more for utility functions like CSS.escape(s) rather than managing stylesheets. Just something to keep in mind to not end up with a confusing API, like if there's globalThis.css and globalThis.CSS.

https://drafts.csswg.org/cssom/#utility-apis

zcorpan avatar Aug 14 '19 14:08 zcorpan

Wouldn't globalThis.css not work since the adoptedStyleSheets currently sits on DocumentOrShadowRoot? I agree we should be weary of collisions, but this fact might mitigate your concern.

calebdwilliams avatar Aug 14 '19 15:08 calebdwilliams

One thing about "css", is that it specifies the exact technology used today for style sheets. If there were to ever be another styling type, other than CSS (that could be mixed into this array along with css), at that point "css" would become a bad name.

I like "styles" (plural) for the name because it reminds me that this is an array of styles even if [onlyOneStyleIsUsed] and the list could potential hold any future technology-type for styling if that ever happens. "styles" is also pretty short (to type) compared to "adoptedStyleSheets". "styleSheets" also comes to mind too as a better choice. "sheets" is another option. "adopted" needs to be removed at the very least.

Lonniebiz avatar Aug 14 '19 15:08 Lonniebiz

We definitely need some array-like structure for the API, since the underlying semantics are array based. I see the need for these operations:

  • Append one or more sheets to the end of the list
  • Prepend one or more sheets to the start of the list
  • Get length
  • Insert one or more sheets at arbitrary indices
  • Access by index
  • Iterate through the list
  • Remove from arbitrary indices
  • Replace the entire list

justinfagnani avatar Aug 14 '19 15:08 justinfagnani

For what it's worth, I think the initial idea was to use moreStyleSheets to draw a parallel with DocumentOrShadowRoot.prototype.styleSheets. I just want to make sure this fact wasn't overlooked, the initial goal was to maintain an association between the two property names. I definitely see value in that, but also realize it isn't strictly necessary, but wanted to make sure that point isn't overlooked moving forward.

calebdwilliams avatar Aug 14 '19 16:08 calebdwilliams

The casing is hard to remember

It's the exact same casing already used in document.styleSheets. I agree it's confusing and I don't like it, but it would be much worse to adopt something different.

'Adopted' is confusing

Legit. Our usage of 'adopted' elsewhere in the platform does indeed imply ownership that's not present here. My original suggestion was, iirc, .moreStyleSheets, which wasn't great either. ^_^

...The acronym is unfortunate

lol, good point

It's long

I get you, but I really think it's important to keep this name close to the existing document.styleSheets, since it's doing essentially the exact same thing. If we're still using "styleSheets", we can't get too much shorter than "adopted".

One thing about "css", is that it specifies the exact technology used today for style sheets.

That's not really a big deal here; we're long, long past the point where a new styling language is a particular concern.

We definitely need some array-like structure for the API,

Yup, need basically all the functionality of an Array here. If we could convincingly fake an Array on the platform, that would be something else, but we can't. :/

tabatkins avatar Aug 14 '19 16:08 tabatkins

I see the need for these operations

As an app developer I would file the following under YAGNI:

  • Get length
  • Insert one or more sheets at arbitrary indices
  • Access by index
  • Iterate through the list
  • Remove from arbitrary indices

I'm also sceptical that I would need to prepend, in practice. I appreciate that there may be some contrived situations in which those operations are necessary, but it doesn't seem to me that the API needs to optimise for them.

I really think it's important to keep this name close to the existing document.styleSheets

I'm not sure I've ever seen anyone use document.styleSheets in the wild. Again, I'm sure it has its uses, but it's not part of most web developers' lived experience, whereas document.adoptedStyleSheets would be. And most usage examples of adoptedStyleSheets I've seen focus on the custom element case, rather than document. So I'm not sure I agree that that's a priority.

Moreover, document.styleSheets is a StyleSheetList rather than a frozen array, so if consistency is a goal then it still falls short.

Rich-Harris avatar Aug 14 '19 17:08 Rich-Harris

As an app developer I would file the following under YAGNI:

As someone who maintains code that already uses adoptedStyleSheets I have to disagree.

Managing the list directly is extremely important for app and component-set theming mechanisms and polyfills that might rely on adoptedStyleSheets. Given that multiple actors may be managing the list, being able to tell if the sheets you care about are already in the list, and what precedence they're at is important.

justinfagnani avatar Aug 14 '19 17:08 justinfagnani

Hum, so you want to be able to test a key, then decide if you insert before of after this key.

dtruffaut avatar Aug 14 '19 17:08 dtruffaut

If the word adopted is confusing as per multiple parents adopting a child. Maybe .appliedStyleSheets would be a better name.

harunhasdal avatar Dec 09 '19 17:12 harunhasdal

If the acronym is really considered regrettable, .extraStyleSheets is another option.

othermaciej avatar Jan 24 '20 18:01 othermaciej

Why not simply .constructedStyleSheets?

The name is a bit longer than .adoptedStyleSheets, but it is clear about exactly what this is for: the structure that holds the style sheets that were created using the constructor.

The only thing I dislike about .appliedStyleSheets is that any of the sheets can be disabled, in which case, they are not applicable.

.extraStyleSheets would probably be fine, but it doesn't communicate any inherent restrictions, especially in the case of getting a NotAllowedError when you try to add a non-constructed sheet.

If I were a developer exploring a new feature called Constructable StyleSheets, I think I would find it intuitive that there is a new attribute called .constructedStyleSheets.

nordzilla avatar Jan 24 '20 19:01 nordzilla

Ostensibly this API will be used for CSS modules as well, so .constructedStyleSheets doesn't quite fit.

calebdwilliams avatar Jan 24 '20 19:01 calebdwilliams

Just putting some thoughts here, the purpose of this API is to share stylesheets across multiple DocumentOrShadowRoots and to assume styles from CSS modules. If we want to keep the -StyleSheets suffix, perhaps something along the lines of sharedStyleSheets.

connectedStyleSheets could also work (the acronym might be confusing), but the language relates to Node.isConnected which is a property on the Node object that illustrates whether or not the node in question is connected to a context object. In this instance the adjective connected is relating to which style sheets are currently connected to the relevant DocumentOrShadowRoot with an understanding that each sheet that can be connected can also be connected elsewhere (where the analogy fails alongside the analogy for adopted).

calebdwilliams avatar Jan 24 '20 20:01 calebdwilliams

I think the name should describe what the author intends to do with the stylesheets, not how they were made. One could imagine future ways to create detached stylesheets that don't involve a constructor, but which might still be desirable to attach to a document at some point. So we should not lock in how they are made IMO.

I am not sure why adding non-constructed stylesheets is not allowed currently. Is it because all other current ways of making stylesheets already start out attached to a document? In which case the error isn't that it's not constructed, it's that it is already attached.

othermaciej avatar Jan 24 '20 20:01 othermaciej

I think it's reasonable to not tie the name to how the sheets are created in case that were to change in the future.

I am just referring to the spec's description of adoptedStyleSheets:

If any entry of adopted has its constructed flag not set, or its constructor document is not equal to this DocumentOrShadowRoot's node document, throw a "NotAllowedError" DOMException.

nordzilla avatar Jan 24 '20 20:01 nordzilla

Alright, I've tired to summarize the list of suggestions made so far with the corresponding concerns.

  • css Concerns: Confusing with CSS. Does not sound related to document.styleSheets.
  • moreStyleSheets
  • extraStyleSheets Concerns: It doesn't communicate any inherent restrictions, especially in the case of getting a NotAllowedError when you try to add a non-constructed sheet.
  • appliedStyleSheets Concerns: any of the sheets can be disabled, in which case, they are not applicable.
  • constructedStyleSheets Concerns: Naming how they were created is strange; we may want to allow CSS moduels or StyleSheet from style element in the future.
  • connectedStyleSheets
  • sharedStyleSheets Concerns: These style sheets are not always shared.

rniwa avatar Jan 25 '20 02:01 rniwa

What about something like cssList? Like a classList, but for style sheets.

Lodin avatar Jan 25 '20 03:01 Lodin

What about something like cssList? Like a classList, but for style sheets.

I think that has the same concern mentioned earlier that it sounds not related at all to document.styleSheets or shadowRoot.styleSheets.

rniwa avatar Jan 25 '20 03:01 rniwa

To me the essence of these things are that "each style sheet listed" is in the form of a javascript variable that points directly to the style in memory and NOT some URL that has to be downloaded and cached from a web server.

This makes me think of names like:

  • referencedStyleSheets
  • linkedStyleSheets
  • styleSheetPointers
  • styleSheetReferences
  • styleReferenceList

By now, isn't just going to stay adoptedStyleSheets anyway? Verbosity!

I'd be cool with styles, styleSheets, or shadowStyleSheets.

Lonniebiz avatar Jan 25 '20 06:01 Lonniebiz

So long as it's not misleading as to the relationship between the stylesheets and the document/shadow root in a problematic way, I think it's nice that a web component's shadow root connectedStyleSheets and a web component's custom element connectedCallback would both use "connected."

...despite them being slightly different senses of connected.

morewry avatar Jan 25 '20 13:01 morewry

Those are different senses of the word connected, I think.

othermaciej avatar Jan 25 '20 21:01 othermaciej

@othermaciej I disagree. isConnected reports if a particular node is attached to some point in a DOM tree. The true analog would be to let stylesheets (constructed or modules) have an isConnected feature as well, let's pretend for a minute they do:

const sheet = new CSSStyleSheet();
someShadowRoot.adoptedStyleSheets = [ sheet ]; // using the old naming convention on purpose here
console.log(sheet.isConnected); // if the feature exists, I would presume this to be true

Therefore we can ask to what is sheet connected? In this instance it is connected to someShadowRoot. Therefore I do think it makes sense to call this API DocumentOrShadowRoot.prototype.connectedStyleSheets and perhaps introduce the CSSStyleSheet.prototype.isConnected (which I can see being useful, but don't have a hard use case for so I won't push it) or even CSSStyleSheet.prototype.connectedTo which could be a NodeList of every tree the sheet is connected to.

calebdwilliams avatar Jan 26 '20 19:01 calebdwilliams

I don’t think the analogy with node’s connectedness quite works because a single node can be associated with at most one document whereas a style sheet can be associated with multiple shadow trees / documents; this is actually problematic though... We probably want to limit it to the same document somehow. Otherwise we’d end up with global object leaks.

rniwa avatar Jan 27 '20 06:01 rniwa

@rniwa, That makes sense, but unless I've missed something (which is possible, you are certainly better prepared to make that sort of statement than I am), there's nothing about connected that necessarily implies a one-to-one relationship; a Node instance, however, does have that implication, but a CSSStyleSheet and a Node are different beasts, but both can feasibly be connected to some context. That's all I'll say about it, thanks for all the hard work on making this API work for everyone.

calebdwilliams avatar Jan 27 '20 14:01 calebdwilliams

@rniwa the suggestion in https://github.com/WICG/construct-stylesheets/issues/97#issuecomment-521299640 was not in your list: sheets.

Though I think the concerns against moreStyleSheets and extraStyleSheets also apply to sheets, but, if a short name is deemed more important, this one seems better than css.

There is some precedent: https://drafts.csswg.org/cssom/#the-linkstyle-interface

zcorpan avatar Jan 27 '20 15:01 zcorpan

@zcorpan That actually makes a lot of sense. If you do let style = document.createElement('style'), the style object will have a property called sheet that is the CSSStyleSheet (or StyleSheet in Firefox) object that would be created here. Calling the API sheets literally makes it a list of sheet objects.

calebdwilliams avatar Jan 27 '20 17:01 calebdwilliams