Reference global class names from within a css module - css

Picture a more traditional web application that is slowly introducing a React component in one page that is complex enough to need it.
We're developing this new UI with Webpack, and we're using css modules for all the new css that the new UI needs. But we still need to reuse some css that's global and provided in the app via a traditional css stylesheet linked in the html.
Therefore we need in our css modules to occasionally write rules that refer to a css class in the global namespace, not a class that's locally scoped to it and therefore converted to a more gem-like long css class name when the app is run:
.container {
// rules for container
}
.container.pull-right {
// rules for when the container element also has the pull-right class
}
In the above example, container is meant to be a css class that the css module will contextualize to the particular component using this module.
But pull-right is a class that exist in a css file available in the page, but not processed by css modules or Webpack. Therefore we need a way (a syntax probably) to tell css modules "hey, leave pull-right as is in your output. Do not mess with it or try to BEM the s**t out of it".
I imagine something like this should exist, but I haven't been able to find it so far by googling around.

To refer to a globally declared class name inside :local scoped css modules you should use :global switch:
.container {
// rules for container
}
.container:global(.pull-right) {
// rules for when the container element also has the pull-right class
}
More detailed explanation in css-modules documentation.

Related

Pass CSS class to Angular Library

I am creating a library using angular CDK for custom modal. I want the application which would use the library to pass the CSS class name with other configuration for the modal window. So that I can apply the class like this in the library.
this.overlayContainer.getContainerElement().classList.add(modalConfig.overlayContainerClass);
I can see the class is applied to the element but no class present.
<div class="cdk-overlay-container overlay-material-design-theme mat-typography custom">
I have defined this in the application component CSS file.
.custom{
width: 100%;
}
The question is how the CSS which is present in the application component would be accessible to library component?
For css classes to work that way you have to put them in a place where view encapsulation is not present.
The place for that is usually in the src/styles.scss.
If you want more structure you can have them in another scss file that src/styles.scss imports.

Angular: Component styles do not cascade to sub-components?

In my app.component.html I have the following, working class assignment.
<body>
<span class="test">SHABOO</span>
<div class="container">
<router-outlet></router-outlet>
</div>
</body>
In the outlet, a component is rendered and it contains the following.
<span class="test">HAZAA</span>
I expected it to get the same style as the first one but it seems that the style doesn't cascade down to the component. It made me uncertain if I'm mistaken about how the styles are supposed to behave between parent and child components in Angular.
I made sure that the name of the class isn't overriden (to exclude the risk of collision). At the moment, I'm putting similar chunks of SCSS code in each component and that's obviously bad practice.
If I #import "../app.component.scss", the styles kicks in. But I was under the impression that even without the import, the style is supposed to cascade.
Angular components use view encapsulation. This is by design so that components are reusable across applications. To treat a component's styles as global, set the view encapsulation mode to none (not recommended).
Instead of using none, register global style files in the Angular CLI styles section, which is pre-configured with the styles.css file.
Component CSS styles are encapsulated into the component's view and don't affect the rest of the application.
To control how this encapsulation happens on a per component basis, you can set the view encapsulation mode in the component metadata. Choose from the following modes:
ShadowDom view encapsulation uses the browser's native shadow DOM implementation (see Shadow DOM on the MDN site) to attach a shadow DOM to the component's host element, and then puts the component view inside that shadow DOM. The component's styles are included within the shadow DOM.
Native view encapsulation uses a now deprecated version of the browser's native shadow DOM implementation - learn about the changes.
Emulated view encapsulation (the default) emulates the behavior of shadow DOM by preprocessing (and renaming) the CSS code to effectively scope the CSS to the component's view. For details, see Appendix 1.
None means that Angular does no view encapsulation. Angular adds the CSS to the global styles. The scoping rules, isolations, and protections discussed earlier don't apply. This is essentially the same as pasting the component's styles into the HTML.
To set the components encapsulation mode, use the encapsulation property in the component metadata:
src/app/quest-summary.component.ts
// warning: few browsers support shadow DOM encapsulation at this time
encapsulation: ViewEncapsulation.Native
ShadowDom view encapsulation only works on browsers that have native support for shadow DOM (see Shadow DOM v1 on the Can I use site). The support is still limited, which is why Emulated view encapsulation is the default mode and recommended in most cases.
External and global style files
When building with the CLI, you must configure the angular.json to include all external assets, including external style files.
Register global style files in the styles section which, by default, is pre-configured with the global styles.css file.
See the CLI wiki to learn more.
This is how angular works. Every component is separated with it's CSS, even if it is child component of a parent. They can't inherit their parent CSS.
Haza span component is child of your app component, but it is separated component. So, you can't get those Shaboo styling to Haza.
Solution:
if you want to maintain same CSS, there are multiple ways.
Recommended way:
a) if it is only for onle class, copy the class to the child component.
b) if it is for huge number of classes, create a css file for them and import them in both parent and child component css.
Example:
#import '../span.css';
you can add this css to styles.css. then you will get it anywhere in the app. if you want this style many places, you can do it.
As #Christopher Peisert mentioned, by using
encapsulation: ViewEncapsulation.Native
end of the #component decorator in child.component.ts. It is not recommended way
The global CSS files are those that are listed in angular.json. All others CSS files are encapsulated by default (this can be removed but is not recommended.)
Keeping your global CSS organised is important as your application grows. What I like to do is create a global styles folder and then add new files for different widgets that I might be altering. Since removal of ::ng-deep these types of changes have to be done in the global scope.
It works like that. If you are in need of having a common style then add it in the global styles.scss file.
If you want a global style put it in the global file styles.css or styles.[Your css preprocessor]
See this example https://stackblitz.com/edit/angular-a5ntm6?file=src%2Fstyles.css
I put test class at the end
.test{
color:red;
}

Host Styles Applied to Component in Angular2

I am currently in the process of creating a custom form component for my Angular component and am running into some styling issues.
I'd like for my input to be able to take variable widths and for them to be controlled by the host component.
For example: <my-input class="input"> would have a corresponding class as such:
.input {
width: 250px;
}
For some reason, if I do this, the rules are just ignored and not applied to my component.
I've seen others wrap their components in what seems like unnecessary divs and then styling those parent divs so that the content inside fits. I don't want to write wrappers just for styling purposes when a CSS rule would suffice.
Would doing this involve using :host ?
Also, how about, host-context(.input) and then applying the classes inside of the consumers CSS ?
I would advice against using ::ng-deep since the Angular team is planning on deprecating it.
If you want to style something within your component from whatever component is hosting yours I suggest you create a host-binding/input and then use that value to bind to your component using the style-directive.

Using CSS to adjust placement of PlaceBarActions in xPages Ext Lib Application Layout Control

I'm using the Notes 9 extension library application layout control and I would like to use CSS to float the place bar actions on the left instead of the right.
Those actions are styled with the lotusBtnContainer class using a float:right property. How do I override that class with my own class that uses a float:left?
I can make the adjustment to the lotusBtnContainer class in firebug but I don't want to touch that class for obvious reasons.
Quick answer: cascading. If your stylesheet is below the stylesheet that defines lotusBtnContainer, then it will override the styles above it. You should be able to add a stylesheet to the page that contains the same definition. One caveat is that you must match the specificity of the lotusBtnContainer definition in the theme stylesheet. If the css definition is td.lotusBtnContainer then in order to override you must also use td.lotusBtnContainer, not just .lotusBtnContainer.
If you need any additional help with this, please add the definition of the lotusBtnContainer from the default css files and I can assist further.
Edit: Additionally, if this doesn't work, adding the class with the style you want like this should override:
.lotusBtnContainer{float:left !important;}

global CSS theming combination with component specific local stylesheets

I'm creating a moduler html/js application with self contained UI components. Each of my UI component may have its own template file (structure), js files (behavior) and css files (presentation).
Now I would like these components to have a 'default' presentation with an own local css file
This is not a problem, and I can define the default styling on the component 'local' css
But in addition I need global theming too, theme css defines styles for the 'whole app'
If an user applies a theme, all local component styles should be overridden by the theme css
I know I can do this with marking all styles on the global theme css as 'important'. But I dont want to go that way. Any other suggestions on how to approach this?
If the elements being styled are addressed via the same selectors e.g. #something li in all stylesheets, then the stylesheet being included later will overwrite anything previously set (unless something is 'important'). This should allow you to do use themes -- just import those themes after the local styles has already being applied.
I'm not sure I understand your question about the local and global styling. But, styles for each components should not interfere with the global style provided you are giving the elements proper names. (It's a good practice to use class/id names instead of long nested selectors like .some-table tr td .another- table tr td { ... } for both rendering performance and readability reasons)
In other word, you can in each of your page write these:
include the base default layout
overwrite the base with global layout
again overwrite with user-define themes
Given the way you structure RequireJS, I would suggest the following:
Allow, or require, styling with style.css in each component
Provide a structure for themes like a themes/ folder which must have the same folder as the components folder
When optimizing or pulling the CSS, if a theme is defined, pull the CSS from the theme folder instead of the main component folder, or fallback to the component style.css (perhaps make this fallback configurable) if not found, with a warning.
You could inject your style element (for each component) using the scope attribute, so it would only affect the DOM scope it's injected to, and not starting from the root element (HTML).
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style#A_scoped_stylesheet
<article>
<div>The scoped attribute allows for you to include style elements mid-document.
Inside rules only apply to the parent element.</div>
<p>This text should be black. If it is red your browser does not support the scoped attribute.</p>
<section>
<style scoped>
p { color: red; }
</style>
<p>This should be red.</p>
</section>
</article>
Browser support (currently): Chrome and FF

Resources