{"id":479,"date":"2024-01-12T16:56:11","date_gmt":"2024-01-12T16:56:11","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=479"},"modified":"2024-01-12T18:30:24","modified_gmt":"2024-01-12T18:30:24","slug":"a-modest-web-components-styling-proposal-an-i-know-what-im-doing-selector","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/a-modest-web-components-styling-proposal-an-i-know-what-im-doing-selector\/","title":{"rendered":"A Modest Web Components Styling Proposal: An &#8220;I Know What I&#8217;m Doing&#8221; Selector"},"content":{"rendered":"\n<p>I think the styling story for <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Web_components\/Using_shadow_DOM\">Shadow DOM<\/a> Web Components is not great. I&#8217;ve got what seems to me like a simple idea that would help that. <\/p>\n\n\n\n<p class=\"learn-more\"><em>Fair warning:<\/em> I&#8217;m just some dude on the internet with an opinion here. I&#8217;m coming at it from an author&#8217;s perspective who has only written a handful of web components. But I like the idea of them, I like the web platform, and I&#8217;ve been trying to watch them for what feels like a long time. I don&#8217;t have the wider perspectives of those who have been in the trenches, speccing and implementing these things.<\/p>\n\n\n\n<p>Let me get right to it. What I mean is using a pseudo selector to break through the Shadow DOM and then be able to style inside it, from any CSS on the page:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">my-component<\/span><span class=\"hljs-selector-pseudo\">::i-know-what-im-doing<\/span> {\n  .something-inside {\n    <span class=\"hljs-comment\">\/* yay, we're in! *\/<\/span>\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now that selector is just tongue-in-cheek (reminds me of React&#8217;s <code>dangerouslySetInnerHTML<\/code>), but the idea I&#8217;m serious about. Maybe it&#8217;s something more straightforward like:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">my-component<\/span><span class=\"hljs-selector-pseudo\">::root<\/span> {\n  .something-inside {\n    <span class=\"hljs-comment\">\/* yay, we're in! *\/<\/span>\n  }\n}\n\n<span class=\"hljs-selector-tag\">my-component<\/span><span class=\"hljs-selector-pseudo\">::root<\/span> <span class=\"hljs-selector-tag\">footer<\/span> <span class=\"hljs-selector-tag\">h3<\/span> {\n  <span class=\"hljs-comment\">\/* When you're in, select and style like normal CSS *\/<\/span>\n} <\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This is not possible right now, and I wish it were. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Current Styling Options of Shadow DOM Web Components and Why I Don&#8217;t Like Them<\/h2>\n\n\n\n<p>I&#8217;ll elaborate on the thoughts I posted in <a href=\"https:\/\/frontendmasters.com\/blog\/light-dom-only\/\">another article<\/a> about Web Components. Here are what seem to be the <em>current<\/em> possibilities for styling a Shadow DOM Web Component:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Styling specific elements with <code><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/::part\">::part<\/a><\/code> is a very niche styling approach that is not a real styling solution. It tosses out the power of CSS (selectors) which seems silly.<\/li>\n\n\n\n<li>Styling by documenting somewhere that certain CSS <code><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/Using_CSS_custom_properties\">--custom-properties<\/a><\/code> are in use, thus you can set them from the outside, and they will cascade in to affect inner styling. This is also limited, not offering the real power of CSS, and to me not a real styling solution. <\/li>\n\n\n\n<li>Styling by injecting a <code>&lt;style&gt;<\/code> tag into some template literal in the JavaScript itself. This feels awkward and ad hoc to me. Writing CSS as a string is not great (you&#8217;d be lucky to get autocomplete, lining, etc.) I&#8217;m not a fan. <\/li>\n\n\n\n<li>Styling with an <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Document\/adoptedStyleSheets\">adopted stylesheet<\/a> means an additional web request for each component or back to using a string which is either awkward or slow. <\/li>\n<\/ul>\n\n\n\n<p>I don&#8217;t want to do any of those. They all force me out of the styling workflow of the rest of my website, and tend to push me towards <em>nope, screw it<\/em> decisions. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Advantages of This Approach<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>You still get the encapsulation. For the most part, anyway. The JavaScript encapsulation stays the same. Even CSS encapsulation is still there. Random CSS will not leak in. You have to be very specific, making the component name part of the selector and using the specific pseudo-selector to reach into these components. That&#8217;s not accidentally done.<\/li>\n\n\n\n<li>You can now style things with the best styling API around: CSS.<\/li>\n\n\n\n<li>You can concatenate\/bundle the styles for your site how you already are doing it. You just&#8230; style stuff.<\/li>\n\n\n\n<li>You can now choose to create Shadow DOM Web Components, and get the excellent feature of <code>&lt;slot&gt;<\/code>s, without being penalized with difficult styling choices.<\/li>\n\n\n\n<li>All the other styling methods are still there.<\/li>\n\n\n\n<li>It would allow people to build and distribute a Shadow DOM Web Component with very basic styling and they could just tell people: <em>hey you wanna style it? Go for it.<\/em><\/li>\n<\/ul>\n\n\n\n<p>OK bye.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I think the styling story for Shadow DOM Web Components is not great. I&#8217;ve got what seems to me like a simple idea that would help that. Fair warning: I&#8217;m just some dude on the internet with an opinion here. I&#8217;m coming at it from an author&#8217;s perspective who has only written a handful of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":488,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[7,68,36],"class_list":["post-479","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-css","tag-shadow-dom","tag-web-components"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/01\/shadow-thumb.jpg?fit=1000%2C500&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/479","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=479"}],"version-history":[{"count":8,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/479\/revisions"}],"predecessor-version":[{"id":489,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/479\/revisions\/489"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/488"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=479"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=479"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=479"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}