Open mercmobily opened 7 years ago
Deleted my prior comments because I didn't realize your original intent was to create a theme file.
OK let's back way up.
First, a custom property != a mixin. Custom properties let you set 1 css property. A mixin lets you set a whole bunch of css properties. Custom properties are natively support by all browsers except for IE/Edge. Mixins are not natively supported by any browser.
Here are the correct patterns for defining and using custom properties and mixins in Custom Elements:
Defining a custom property:
html {
--background-color: red;
}
Using a custom property in an element:
:host {
background: var(--background-color, blue); /* blue is the fallback value */
}
Defining a mixin:
html {
--background-mixin: {
background-image: url('...');
background-color: pink;
background-position: 0% 0%;
}
}
Using a mixin in an element:
:host {
background-image: url('...');
background-color: green;
background-position: 50% 50%; /* The above 3 properties are fallback values */
@apply(--background-mixin);
}
The way your element exposes styling hooks is exactly as I have outlined above. For example, you could say that the above custom property element exposes a custom property of --background-color
. The consumer of your custom element can choose to set this value to theme your element.
If you're building a custom element it probably should not define a value for a custom property/mixin, unless you are only using that property internally. Instead it should only consume properties/mixins. This is because you don't want the act of including a custom element to suddenly change the theme of your entire site. That would violate the idea of css scoping/encapsulation.
/* Inside a Custom Element's shadow root... */
:root {
--background-color: red; /* probably bad */
}
:host {
background: var(--background-color, red); /* Good. We only consume properties */
}
Also I would suggest avoiding the use of :root
and instead use html
when you are trying to define document level custom properties. I know the docs say to use :root
and technically I think that's fine to do at the document level, but Polymer also used to allow you to use :root
inside of the Shadow DOM and that was actually a bug. Avoiding :root
all together might just be a good habit to get into. cc @arthurevans to correct me if I'm totes wrong about stuff
@robdodson wait a sec, my man intent wasn't about creating a theme, as much as explaining how styling works in general. Then, this info is usable to create themes, consume them, etc.
I know mixins and properties are different. The confusion in the document came from the fact that I see mixins as properties are strictly inter-related -- they are just used differently. I mean, writing:
:root {
--my-property: red;
}
Or:
:root {
--my-mixin: {
color: red;
background-color: blue;
...
}
}
In my little head is still "assigning" something to the "variables" --my-property
and --my-mixin
. Sure, one is a property and the other one is a mixin. But...
I updated my post, adding both a mixin and a property. This actually makes it more complete.
Thank you!
(Ah, let me know if I should change :root with HTML too -- I did't address that in your response, sorry!)
Hey @mercmobily. Sorry for the late response. Let me go though your first section, with advance apologies for being nitpicky.
In Polymer (and web components in general), CSS encapsulation is enforced by the following principle:
Just to clarify, we're talking about shadow DOM here, not anything specific to Polymer. (Except for style modules, at the end, and some details about Polyfills.) I note this because in the past we've had confusion about what is custom elements vs. what is shadow DOM vs. what is Polymer.
Global styles won't apply to tags in the shadow DOM of a component
This depends on what you mean by "apply". Really, when we're talking about shadow DOM style encapsulation, what we're talking about is selector matching. A selector in the main document can't match an element inside a shadow tree. A selector inside a shadow tree can only match:
:host
),<slot>
(with ::slotted()
).If you're using shady DOM, note that CSS styles in the main document can leak into shadow trees. The fix for this is to define document-level styles inside a custom-style
element.
The only things that can "leak" from a global
I kept on getting confused by the styling options in Polymer. Also, I am employing a great web designer with no Polymer experience, and I had a bit of a hard time explaining everything.
So, I wrote this short guide. It sums up nicely the whole "CSS" thing so that anybody can hopefully understand. I feel it's important to have one file that:
It would be awesome if you could:
1) Check that it's all factually correct (I am especially worried about having used the right technical terms throughout) 2) Give me the OK to turn this into a blog post (I will flesh things up) 3) Include it in the official documentation "somehow".
I realise that the documentation covers all of this, but I think the documentation can be made stronger in terms of best practices etc.
I could just publish this in Free Software Magazine, but I think it's important enough to be in the main documentation...
Overview
In Polymer (and web components in general), CSS encapsulation is enforced by the following principle:
<style>
are CSS custom properties and CSS mixins that match the:root
selectorimport
ed 3)include
d explicitly by thestyle
tag of the component or document.Here is a verbose explanation of all this.
Defining global custom properties with
:root
:my-props.html
Create a file with just the
<style>
tag (with the thecustom-style
attribute). Any property or mixin defined within a:root
selector will be set in the CSS global scope, and will therefore be available to modules and main documents.my-props.html
Include properties in the main document
Here as soon as
my-props
is loaded, the custom CSS properties are added to the CSS global scope (in this case, the--red
mixin and the--main-background
property). So, they can be used at will immediately. Also, since there is no shadow dom involved (this is just a plain HTML file), the.blue
style will also work.file.html
Import props in an element
Here too, as soon as
my-mixinx.html
is loaded, the custom CSS properties are available (in this case,--red
). However, other selectors (like.blue
) will fail as they are not allowed to pierce through the shadow DOM. So, within a module, only CSS custom properties and mixins matching:root
can actually be used within that module.my-element.html
Defining CSS selectors and use them in files and modules:
my-classes.html
If you want to define styles and make them available both within an element or a main HTML document, you will need to encapsulated them and then include them in the element or the main HTML document.
Create a module where the template only contains a
<style>
-- no actual HTML norPolymer()
call:my-classes.html
Include classes in the main document
Just
import
ing such a file will not affect CSS styles in the document -- it will just define a template within a<dom-module>
element. In order to actually enable those styles, they need to beimport
ed in a<style>
tag.file.html
This will have the effect of actually applying the styles defined in
my-classes.html
.TODO: check that the style will strictly only apply to that document, or if standard CSS rules will apply.
Import classes in an element
You can import
my-classes.html
, and theninclude
it in the element'sstyle
tag, in order to have the extra classes available within the element's shadow DOM:my-element.html