53

Say we have a LWC with the following template in a component named example:

<template>
    <lightning-textarea class="test"></lightning-textarea>
</template>

And some css to go with it:

.test textarea {
    min-height: 500px;
}

The expected behavior is that the lightning-textarea will be 500px tall because the nested textarea has been made 500px tall.

The actual behavior is that nothing happens. The reason for this is that the compiled css will be:

.test[c-example_example] textarea[c-example_example] {
    min-height: 500px;
}

And the compiled (relevant parts of the) html will be:

<lightning-textarea c-example_example lightning-textarea_textarea class="test"> 
   <textarea lightning-textarea_textarea></textarea>
</lightning-textarea>

It's obvious that the CSS Module Scoping has scoped the textarea element to its parent, lightning-textarea and not our example component. This is an issue because the CSS processor has appended [c-example_example] not only to the .test part of the selector, but textarea as well.

It makes sense that CSS would be scoped downward, which is how Aura components handled scoping, but in LWC it's actually entirely isolated, so neither parent nor child elements can target it.

Is there any way around this? Or plans to support targeting child components? Being able to override and tweak the CSS of the standard component library was a very handy feature of Aura components, allowing customized appearances without having to rewrite the base component from scratch.

On top of that, this means that you can't reuse your own components in different contexts, giving them different styles in each. The component itself must be responsible for all of its styling. While this is possible it requires a lot of conditional class assignments which is frustrating.

2
  • 12
    This is a total nightmare.
    – Robs
    Jul 31, 2019 at 21:04
  • 1
    Wow. How can they introduce LWCs when there is no standard solution for styling embedded standard components, like lightning-accordion?
    – Hans
    Dec 20, 2019 at 14:56

8 Answers 8

12

As of Winter `21, you can use styling hooks (beta): https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.create_components_css_custom_properties

1
  • Marking this as the new accepted answer as this is the implementation of ::part and ::theme that pmdartus alluded to, and is the only officially recommended solution from Salesforce (even if it is limited in functionality) Nov 2, 2021 at 15:46
34

We ran into the same problem. I think it is something that Salesforce should definitely address as it is the biggest limitation of LWC compared to Aura components that we have encountered so far.

For example, we wanted to give a different color to a lightning-icon component and the only way to do this is to change the css fill color of the svg element inside lightning-icon. But that svg is not accessible/visible to our component's css because of the strict CSS isolation enforced by LWC. Re-creating our own version of Salesforce base components or submitting an Idea anytime we want to do a little ui tweak to one of them does not seem viable to us.

The workaround that we ended up using is to put the CSS that we wanted applied to the inner shadow DOM of Salesforce Base Components in a static resource. Then we used the loadStyle method of lightning/platformResourceLoader module to load that css. The styles loaded this way do apply to the inner elements within Salesforce base components.

Documentation for the loadStyle method is available here: https://developer.salesforce.com/docs/component-library/documentation/lwc/create_third_party_library

Another approach would be to encapsulate your LWC component inside an Aura component and put the CSS targeting inner elements in the css file of that aura component. Aura components do not enforce strict CSS encapsulation so that CSS will apply.

Neither workaround is ideal so we are looking forward to a better solution provided by Salesforce. The ::part and ::theme proposal seems promising but it looks like it won't be available for a while.

3
  • The LoadStyle workaround is very nice. Alternatively, I was also able to hard-code the slds code, but that takes away the brevity of the lightning tags. I think it's very reasonable to have a boilerplate folder for all the inner-shadow-css available to each html template. Later, when they make those parts available, you can just migrate the external css to the internal. Also, I agree that the shadow root blockage is the biggest shortcoming of LWC compared to Aura, but this workaround takes that away.
    – DaveS
    Apr 21, 2019 at 16:13
  • I find it quite interesting that CSS loaded through the loadStyle does allow overriding the inner elements while the CSS coming from the .CSS of the lightning bundle doesn't allow this... Working together with a designer, who doesn't yet think in the context of component isolation and specificities from LWC, I must say I find the loading of the styles through a static resource (like you would usually do with traditional VF pages) seems to work best at this time.
    – KoenVM
    Sep 26, 2019 at 12:35
  • Much thanks, using the Aura component Parent's CSS file worked beautifully in our case. We are migrating one-by-one a composed Aura component however, so eventually it looks like we will have to use the loadStyle "hack". May 6, 2020 at 20:28
32

LWC is enforcing the shadow DOM style scoping, so you can't currently style other Elements outside your shadow tree.

That being said, there is the on-going ::part and ::theme proposal that would allow components to safely expose some of their internals outside their shadow tree to be customized. This feature will be shipped in Chrome 73 and the rest of the browser vendors are supportive. We are currently evaluating how to add this in LWC and in the lightning base components.

14
  • 5
    Welcome to SFSE! Always love having people on the Salesforce team come by.
    – Adrian Larson
    Jan 21, 2019 at 14:28
  • 1
    This is great news! I hope to hear more about this down the road Jan 23, 2019 at 0:04
  • 7
    It seems ridiculous that we have to resort to creating our own duplicates of standard base components if we want our own styling. Didn't have to do that in aura or visualforce. But LWC is better? Apr 26, 2019 at 19:18
  • 3
    @pmdartus I'm eager to know if you have any updates on ::part and ::theme implementation in LWC.
    – devforce
    May 8, 2019 at 5:38
  • 2
    @pmdartus another friendly prod to see if Salesforce development is making any progress with this.
    – Phil W
    Jun 10, 2020 at 15:56
18

The workaround that I have been using is to create a <style> tag and add it to the dom. This is somewhat dangerous if not done correctly because it can affect the entire css of the page including standard Salesforce UI

export default class Example extends LightningElement {
  renderedCallback() {
    if (this.hasRendered) return;
    this.hasRendered = true;

    const style = document.createElement('style');
    style.innerText = `
      c-example lightning-textarea textarea {
        min-height: 500px;
      }
    `;
    this.template.querySelector('.some.element').appendChild(style);
  }
}

Note that the selector uses c-example to scope the css, but doesn't necessarilly have to do so.

4
  • 3
    this worked perfectly for m
    – aaron
    Jul 29, 2019 at 19:13
  • works perfectly for me too
    – dev4life
    Sep 9, 2020 at 3:05
  • 2
    This seems to have stopped working
    – Steven.B
    Feb 25, 2021 at 17:02
  • You could make a special component that has an api level that still allows this. The component would do ONLY this and you could tell it what to target via an api method. Dec 11, 2022 at 18:30
7

No, CSS isolation is intentional. The code you see now in the browser will eventually just render as Shadow DOM, which are essentially black boxes from the outside. As such, you'll need to resort to building your own custom components so you have better control over them.

I do think it's a bit silly that you can't explicitly set the height for a textarea, though. You might want to propose an Idea for that. Something about being able to have a supported method for inserting extra styles for standard components.

I do know that LWC is still being worked out, so we don't know what the final result will look like for some time yet. It'd be a lot less of a wait, though, if you just wrote your own by borrowing from SLDS and adding extra support for that.

1
  • Any idea how community themes will be applied to lwcs, given their encapsulation? Jun 20, 2019 at 22:57
3

Just forget the scoped stylesheet that comes with a Lightning Web Component (until they present a solution for this issue) and define the styles of your component in a global stylesheet that you add as a static resource:

c-record-job-details {
 // Add styles for your LWC here
}

I had two stylesheets, a scoped one for the component and a global one for the embedded components within that LWC, but this got too confusing.

1

I wanted to chime in on this as I had the same issue. I worked around it by using the standard <textarea></textarea> and grabbing the value via this.temlate.queryLocator('textarea').value.

HTML

  <h1>
    Enter a CSV
  </h1>
  <textarea placeholder="Example: 9999999999,8888888888,7777777777,...">
  </textarea>

CSS

:host textarea{
  width: 100%;
  min-height: 300px;
}

:host h1{
  font-size: 18pt;
  color: black;
  font-style: bold;
}

JS

handleSubmit(){
    var rawText = this.template.querySelector('textarea').value;
    console.log(rawText);
}

I only have one textarea on my form, but you can be much more specific if needed. I started here:

https://developer.salesforce.com/docs/component-library/documentation/lwc/create_components_dom_work

I havn't tried it but I suspect this might also be useful: https://www.w3schools.com/jsref/met_document_queryselector.asp

0

For custom components you will be able to use light DOM in Summer '22, which allows you to open the scope of your components up, however this doesn't apply for standard components

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .