global CSS theming combination with component specific local stylesheets - css

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

Related

In an angular 9 app, what should be more preferred; global styles or component level styles

We've two options to keep styles in an Angular 9 app; global styles in styles.css or individual component level styles in the component css file.
If looked at the project from performance perspective;
what should be the preferred way?
Should we keep all styles in a single global style.css file or keep each component related styles in their component.css file?
To answer this question we have to refer to the Angular official doc.
By using Using component styles you will have a better modular design.
Angular can bundle component styles with components, enabling a more
modular design than regular stylesheets.
But, if there are some styles that are common between more than one component it's better to have a shared css and e.g. if you use pre-processor such as .SCSS, LESS, SASS, ..., you can have some _var.scss to define general styles such as base color, fonts, ... and then #import in other component styles or just register global style files in the styles section which, by default, is pre-configured with the global styles.css file.
So, using component styles provide scoping restriction and View encapsulation for your app. This scoping restriction is a styling modularity feature:
You can use the CSS class names and selectors that make the most sense
in the context of each component.
Class names and selectors are local to the component and don't collide with classes and selectors used elsewhere in the application.
Changes to styles elsewhere in the
application don't affect the component's styles.
You can co-locate the
CSS code of each component with the Typescript and HTML code of the
component, which leads to a neat and tidy project structure.
You can
change or remove component CSS code without searching through the
whole application to find where else the code is used.
There are several ways to add Global (Application wide styles) styles to the Angular application. The styles can be added inline, imported in index.html or added via angular-cli.json. The angular allow us to add the component specific styles in individual components, which will override the global styles.
I don't think there is much (if any at all) significant difference in performance. The global or component style distinction is all about the scope of those styles and maintainability of your codebase. Generally its good idea to keep everything in components as they are scoped to themselves and will not accidentally override other same styles from anywhere else. And global styles should stay mostly to theming, utility, helpers etc.
Besides you have an option to make component style global as well, if for some reason you need to do that.
step to define/preferable way for global style
Create _base.scss file in the css folder (first create css folder).
import other helping scss file in _base.scss file
add the entry of _base scss file in style.scss file (style.scss available when we create the folder).

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;
}

How do I overwrite CSS generated from an outside widget?

I've embedded a widget on my page that links to this javascript file:
https://widget.zola.com/js/widget.js
The widget is generating a header section which i'd like to remove.
https://widget.zola.com/v1/widget/registry/taylorandjaredseptember7/html?:1
I've inspected the element and was able to target the section and add a display: none to it. That worked, but when I copied the code into my CSS style sheets, it was not working. I even tried adding !important to it with no luck.
Is there something obvious that I'm missing?
This is the code I added to my stylesheets.
.registry-header {
display: none !important;
}
I also tried targeting the classes it was nested in, like so:
.row registry-header-section .col-xs-12 .registry-header {
display: none !important;
}
Other background info that might be helpful:
- My site is a Wordpress site using the Divi theme.
Establish where the current rules are being generated from in the Document Tree and then use this question and answer to find how to effectively overwrite these rules.
Possible Routes:
You may need to use an id tag on the element and apply the style to the #id, because this will overwrite .class level styling.
You need to be as specific as possible with your targetting; your second example is better than your first.
Remember if the widget uses just a JS file then it's probably editing the CSS via Javascript inline, so it will be doing so inline, therefore you may need to add the style adjustment overwrite inline into the page itself. Set your <style> block to appear as late in the <head> as possible and add !important to the elements required
Create your own Javascript script to load after their widget script and to force CSS to adapt as you want it, with javascript or jQuery code blocks.
Crazy idea.... but it might just work.
You would first need to export from your Browser Inspector the current applied styling generated by the widget and save this to your own (domain-local) CSS file.
You can then use Content Security Policy to specifically block 'unsafe-inline' and 'unsafe-eval' in your style-src: part to block javascript and other inline styling from being applied to the page.
Replacing this with your export CSS style sheet should avoid Javascript/inline styling and allow you to tweak the styling as you need by simply editing your CSS code. You ca fine tune this depending on your dependancies and codebase.

is it possible to write CSS for all Angular "hosts" or do we have to select each host individually

The Angular documentation for :host does not mention that we can style all host elements at once. I have added this CSS at a “global” level:
:host {
width: 100%;
}
but there was no effect. However, this works fine in the CSS at the component level:
:host(app-search) {
width: 100%;
}
where app-search is a component, app-search.component.ts.
Is is possible to write a :host selector for all components or must this be declared multiple times at the component level?
By its very definition (or specification), :host can never be used at a global level. It is created to use from component level and to select the parent component (which is called shadow host) from the children (which is called shadow tree).
For more clarification, Angular's :host selector is a special selectors from the world of shadow DOM style scoping (described in the CSS Scoping Module Level 1 page on the W3C site).
The angular documentation clearly specifies that you should use this selector to select the parent component from within the child component. But it may seem unclear to you if you don't have any idea how shadow tree works. see the documentation.
If you need to style any component from a global stylesheet, there is a style.css file automatically added at a global scope in Angular. Just put your CSS in that file and you can find it available globally in all components.
Component level CSS files make your CSS modular. This is a great feature because:
You can use the CSS class names and selectors that make the most
sense in the context of each component.
Class names and selectors are local to the component and don't collide with classes and selectors
used elsewhere in the application.
Changes to styles elsewhere in the
application don't affect the component's styles.
You can co-locate
the CSS code of each component with the TypeScript and HTML code of
the component, which leads to a neat and tidy project structure.
You
can change or remove component CSS code without searching through the
whole application to find where else the code is used.
Although it is configurable, I strongly recommend not to use ViewEncapsulation.None. It will make kill all your CSS modularity which you can avail easily using global CSS files without affecting the scoping restriction.
In your app-search.component.ts file, you could set:
encapsulation: ViewEncapsulation.None
like this
#Component({
templateUrl: 'app-search.component.html',
styleUrls: ['app-search.component.css'],
encapsulation: ViewEncapsulation.None
})
This prevents you from having to rewrite styles and enables styles on a global level.
You could also try applying the styles directly into the index.html file. These styles will also be global, preventing you from rewriting styles at the component level.

Disable / overriding Joomla template CSS

I am building a module in Bootstrap for Joomla. It has its own stylesheet, but the activated template (where I test it in) also uses Bootstrap and classes which adds some CSS to my module (tables, buttons, etc.).
I want my module to look the same in all different templates of Joomla. Is there a way of disabling the CSS of the template for my module so it just looks same on every template? Or do I have to declare every single line in CSS (with !important, because I think that's a lot of work?)
The CSS is rendered within an HTML document, so you can't just "disable" it on a piece of the page (which is your module).
One possible approach is to render your module inside an <iframe> so it would be a separate document into the main HTML document. But I'm not sure if this would be good/recommended, so I would rather rewrite my CSS rules so they all are inherited from my module.
For example: if your module is the "Fancy Contact Module", you can use an wrapper div like <div class="fancy-contact-module"> and write all your CSS rules like:
.fancy-contact-module p {
color: green;
}
.fancy-contact-module a {
text-decoration: none;
}
and so on.
You can also use your wrapper div to apply Reset CSS or Normalize CSS (or any other similar tool), so you won't need to override all CSS rules manually. You can see more about Reset and Normalize here: What is the difference between Normalize.css and Reset CSS?

Resources