Tailwind - css rule is invisible if I use layer - tailwind-css

Do you have any ideas why #layer in Tailwind CSS doesn't work?
If I write in my styles.css for example
h1 {
#apply text-2xl;
}
it works but if I do:
#layer base {
h1 {
#apply text-2xl;
}
}
it doesn't. It just doesn't see this style.

I have got same error but i figured out from inspecting elements that inherited styles have been applied then i add some more styles to strong elements then mounted css styles have more precedence because of selectors and it worked..
#layer base {
h1 {
#apply text-green-600 font-bold text-4xl;
} strong {
#apply text-gray-800 font-extrabold text-2xl;
}
}

It's possible that your h1 style is getting purged by Tailwind's styler purging process: https://tailwindcss.com/docs/controlling-file-size:
Using the #layer directive will also instruct Tailwind to consider
those styles for purging when purging the layer.
Since, presumably, you're not referencing the h1 style with #apply, maybe Tailwind is considering the style unused. Although, one would hope that Tailwind would not purge a tag-based selector.
Take a look at the CSS file that is built, either on the file system or inspector in the browser, and look for your h1 styles.
From the Tailwind docs, maybe try adding h1 to your whitelist - although I don't think it will work since the whitelist seems to want class-based selectors.
// tailwind.config.js
module.exports = {
purge: {
content: ['./src/**/*.html'],
// These options are passed through directly to PurgeCSS
options: {
whitelist: ['bg-red-500', 'px-4'],
}
},
// ...
}
I recommend asking if tag selectors work with layers on the Tailwind Discord or forum: https://tailwindcss.com/community

Related

Controlling the specificity of CSS Modules in a Next.js App

I'm trying to figure out a good workflow of how to use Tailwind together with CSS Modules in Next.js, but I'm running into some tricky problems regarding specificity and the order in which styles are inserted by Webpack.
Consider the following use case: I want to create a reusable Button component whose styles can be overridden with utility classes. Option 1 is to extract the component, as mentioned in the Tailwind Docs:
/* button.jsx */
export const Button = props => <button {...props} className={`btn {props.className}`} />
and in my tailwind.css file I'd add the classname in the #layer directive:
#tailwind base;
#tailwind components;
#tailwind utilities;
#layer components {
.btn { #apply ... }
}
This is nice because I can override any of the buttons styles with utility classes, since they have higher specificity. However, I see a few minor problems here:
the class is now global, so it's included in every page even if I don't use the component
the style and component are no longer colocated - this might get messy if I create many such classes
Option 2 would be to use a CSS Module and apply the classes like this:
/* button.module.css */
.btn { #apply ...}
/* button.jsx */
import styles from "./button.module.css";
export const Button = props => <button {...props} className={`${styles.btn} {props.className}`} />
This way the CSS only gets loaded when the component is used, and the styles are colocated. Problem here is that in Next.js CSS Modules are inserted after global CSS, so they have higher specificity. Which totally makes sense, usually I'd want my CSS Modules to be able to override global styles. However, in this case I'd like them to be inserted before my global styles so that I can override them with utility classes.
I assume this should be possible by adjusting the Webpack config? Does anyone proficient with Webpack know how to achieve this?
I actually found a nice solution in tailwind v3.0, which is using the new important option. In your tailwind.config.js you can now add this line:
module.exports = {
// ...
important: '#__next'
}
This way, all your utilities are getting prefixed with #__next (the root element in Next.js), which increases their specificity above that of CSS Modules.
Go for the second option and simply add ! to the property to make that important.
/* button.module.css */
.btn { #apply !mb-0 }

TailwindCSS and Wordpress – Styling plugin output

I'm trying to figure out the best way of using TailwindCSS for WordPress theme development. I'm confused about the best way to style html output that you don't have easy control over like a plugin. Or for example a menu, how to style item states that WP provides useful classes to style like .current_page_item.
Previously I would typically dequeue plugin css and then add my own css rules applied using the css classes that the plugin outputs.
I was thinking I could do something similar using tailwinds #apply feature to apply a bunch of tailwind classes to an element using the plugins class name.
e.g.
.plugin-btn { #apply bg-blue-500 text-white font-bold py-2 px-4 rounded; }
or in the case of a menu:
.current_page_item { #apply text-red-500 hover:text-blue-500 }
This method seems a bit awkward with Tailwind v1.x as #apply didn't work with responsive class variants or pseudo class variants but v2 it seems #apply does work with these now.
Is this a good solution. What do other people do?
So if I understand you correctly, you tend to remove the styling of plugins & redo it your self? And the problem you have now is to create the responsive styling (using Tailwind CSS)?
If that's the case you could do something like:
// This would be the default style from a mobile-first perspective
.plugin-name {
#apply w-full;
}
// This would be the style from a MD perspective (I think iPad devices and up?)
#screen md {
.plugin-name {
#apply w-1/2;
}
}
When I need to add hover, focus etc I do it like:
When using SCSS:
.item-class-name {
#apply text-black ...;
&:hover {
#apply text-white bg-black;
}
}
When using CSS:
.item-class-name {
#apply text-black ...;
}
.item-class-name::hover {
#apply text-white bg-black;
}
I'm currently creating a (personal for now) starter theme which is built on TailWind CSS & AlpinejS, and using the laravel-mix setup.
This makes it easier to achieve something like:
// app.scss file in which I add the tailwind components
#tailwind base;
#tailwind components;
#tailwind utilities;
// Additional scss files are divided in components folder
#import './components';
// You could add a 'plugins' file like
#import './plugins';
// In the plugins file you would import all the plugin related styling files...if that makes sense.

How to scope Tailwind Css

I cannot find a good way to scope tailwind CSS when including it in a system where I don't want it to apply globally that works with custom build options.
Essentially I want to do this:
.tailwind{
#import "tailwindcss/base";
#import "tailwindcss/components";
#import "tailwindcss/utilities";
}
But PostCSS importer doesn't like this due to the fact it imports before the tailwind placeholders are replaced. So the only way to make it work is to break the build into 2 stages then import the compiled css like:
.tailwind{
#import "tailwindcss.css";
}
It works but it breaks some of the css rules which show up in dev tools.
Is there a better way to scope tailwind to stop it interfering with other systems?
I've found that you can use postcss-nested for this. Install the plugin, add it as the first plugin to your PostCSS config file and this should work:
.tailwind {
#tailwind base;
#tailwind components;
#tailwind utilities;
#tailwind screens;
}
From the docs...
The prefix option allows you to add a custom prefix to all of Tailwind's generated utility classes. This can be really useful when layering Tailwind on top of existing CSS where there might be naming conflicts.
For example, you could add a tw- prefix by setting the prefix option like so:
// tailwind.config.js
module.exports = {
prefix: 'tw-',
}
You will achieve this by setting important in the tailwind config to your parent class or id. See docs.
// tailwind.config.js
module.exports = {
important: '.tailwind',
}
Unfortunately, this seems to only be affecting the components and utilities styles... the base styles will remain unaffected.
As requested leaving my answer here:
I used the prefix as suggested by Lanny
// tailwind.config.js
module.exports = {
prefix: 'tw-',
}
And then made my tailwind css file like this:
#import "tailwindcss/components";
#import "tailwindcss/utilities";
Then I just manually copied any base styles that I wanted manually into my main css file and manually changed anything that conflicted.
I think the tricky part here is actually about the preflight/reset.css. You want to fend off external styling from coming to your scope but also don't want to pollute the external system with your tailwind style.
My current set up include following steps:
In tailwind.config.js we disable the prefight, defining a prefix tw-, and adding an extra selector #app via option important. The last change will add an extra css selector to output, e.g. #app .tw-mb-4.
module.exports = {
important: '#app',
prefix: "tw-",
corePlugins: {
preflight: false,
},
Find and copy the content of base.css from node_modules folder before pasting it into a scss file with a parent selector #app. You can compile this using any online SCSS compiler. This will help you only reset styling within your scope.
#app {
/*content from base.css*/
}
Copy compiled the styling from #2 and paste to the beginning of your tailwind css file.
Structure the html so you contents are wrapped within a div with the id of #app.
Tailwind's important option doesn't seem to add selector to #layer component so you will have to include that in your component styling.
#layer components {
#app .page-h1 {
#apply tw-mt-0 tw-mb-2 tw-text-center tw-leading-8 tw-text-4xl md:tw-text-5xl;
}
}
According to the docs:
If you’d like to completely disable Preflight — perhaps because you’re integrating Tailwind into an existing project or because you’d like to provide your own base styles — all you need to do is set preflight to false in the corePlugins section of your tailwind.config.js file.
This seems to work with Wordpress in the admin but it does remove the normalization, like cursor: pointer on button hover, for example.
What I have done is this
module.exports = {
prefix: 'tw-',
content: [
"./src/**/*.{html,ts}",
],
theme: {
extend: {},
},
purge: {
enabled: true,
content: ['./src/**/*.{html,ts}']
},
plugins: [],
corePlugins: {
preflight: false,
}
}
It will reduce build size as ,I have purged CSS, disable global CSS,as I have used preflight, and now If u want to apply tailwind class use as
<div class="tw-m-4"></div>
As we have used tw in prefix

How to use predefined css classes from Vue.js libraries?

I work with CSS rarely, but I really want to style my chart. The chart is from a vue.js library and has predefined CSS classes. I just don't know how I am able to access them.
HTML:
CSS:
This is how the document describes the use of CSS with the library:
It's hard to get the full picture only from the images you shared. But it should be relatively easy to just override the default styles that the library uses. If you know what the class names are.
For example:
<style scoped>
year: {
display: block;
}
</style>
Take a look at scoped styles docs.
What you need is a "deep" selector.
So if you want to override child component's styles your css should look like
.vtc-statistik /deep/ .vtc {
}
The thing is that your scoped styles get compiled to
.daten[data-v-bla-bla]{
...
}
b[data-v-bla-bla]{
...
}
/* and .vtc-statistik with nested .vtc */
.vtc-statistik .vtc[data-v-bla-bla] {
...
}
in order to work the way you expect it to work it should get compiled to
/* */
.vtc-statistik[data-v-bla-bla] .vtc{
...
}
where data-v-bla-bla is a unique id of your component.
Btw. Nested styles are not part of CSS specifications. You should use SCSS / PostCSS / Less to process them.

How and where to use ::ng-deep?

How and where can one use ::ng-deep in Angular 4?
Actually I want to overwrite some of the CSS properties of the child components from the parent components. Moreover is it supported on IE11?
Usually /deep/ “shadow-piercing” combinator can be used to force a style down to child components. This selector had an alias >>> and now has another one called ::ng-deep.
since /deep/ combinator has been deprecated, it is recommended to use ::ng-deep
For example:
<div class="overview tab-pane" id="overview" role="tabpanel" [innerHTML]="project?.getContent( 'DETAILS')"></div>
and css
.overview {
::ng-deep {
p {
&:last-child {
margin-bottom: 0;
}
}
}
}
it will be applied to child components
I would emphasize the importance of limiting the ::ng-deep to only children of a component by requiring the parent to be an encapsulated css class.
For this to work it's important to use the ::ng-deep after the parent, not before otherwise it would apply to all the classes with the same name the moment the component is loaded.
Using the :host keyword before ::ng-deep will handle this automatically:
:host ::ng-deep .mat-checkbox-layout
Alternatively you can achieve the same behavior by adding a component scoped CSS class before the ::ng-deep keyword:
.my-component ::ng-deep .mat-checkbox-layout {
background-color: aqua;
}
Component template:
<h1 class="my-component">
<mat-checkbox ....></mat-checkbox>
</h1>
Resulting (Angular generated) css will then include the uniquely generated name and apply only to its own component instance:
.my-component[_ngcontent-c1] .mat-checkbox-layout {
background-color: aqua;
}
USAGE
::ng-deep, >>> and /deep/ disable view encapsulation for specific CSS rules, in other words, it gives you access to DOM elements, which are not in your component's HTML. For example, if you're using Angular Material (or any other third-party library like this), some generated elements are outside of your component's area (such as dialog) and you can't access those elements directly or using a regular CSS way. If you want to change the styles of those elements, you can use one of those three things, for example:
::ng-deep .mat-dialog {
/* styles here */
}
For now Angular team recommends making "deep" manipulations only with EMULATED view encapsulation.
DEPRECATION
"deep" manipulations are actually deprecated too, BUT it's still working for now, because Angular does pre-processing support (don't rush to refuse ::ng-deep today, take a look at deprecation practices first).
Anyway, before following this way, I recommend you to take a look at disabling view encapsulation approach (which is not ideal too, it allows your styles to leak into other components), but in some cases, it's a better way. If you decided to disable view encapsulation, it's strongly recommended to use specific classes to avoid CSS rules intersection, and finally, avoid a mess in your stylesheets. It's really easy to disable right in the component's .ts file:
#Component({
selector: '',
template: '',
styles: [''],
encapsulation: ViewEncapsulation.None // Use to disable CSS Encapsulation for this component
})
You can find more info about the view encapsulation in this article.
Make sure not to miss the explanation of :host-context which is directly above ::ng-deep in the angular guide : https://angular.io/guide/component-styles. I missed it up until now and wish I'd seen it sooner.
::ng-deep is often necessary when you didn't write the component and don't have access to its source, but :host-context can be a very useful option when you do.
For example I have a black <h1> header inside a component I designed, and I want the ability to change it to white when it's displayed on a dark themed background.
If I didn't have access to the source I may have to do this in the css for the parent:
.theme-dark widget-box ::ng-deep h1 { color: white; }
But instead with :host-context you can do this inside the component.
h1
{
color: black; // default color
:host-context(.theme-dark) &
{
color: white; // color for dark-theme
}
// OR set an attribute 'outside' with [attr.theme]="'dark'"
:host-context([theme='dark']) &
{
color: white; // color for dark-theme
}
}
This will look anywhere in the component chain for .theme-dark and apply the css to the h1 if found. This is a good alternative to relying too much on ::ng-deep which while often necessary is somewhat of an anti-pattern.
In this case the & is replaced by the h1 (that's how sass/scss works) so you can define your 'normal' and themed/alternative css right next to each other which is very handy.
Be careful to get the correct number of :. For ::ng-deep there are two and for :host-context only one.
Just an update:
You should use ::ng-deep instead of /deep/ which seems to be deprecated.
Per documentation:
The shadow-piercing descendant combinator is deprecated and support is
being removed from major browsers and tools. As such we plan to drop
support in Angular (for all 3 of /deep/, >>> and ::ng-deep). Until
then ::ng-deep should be preferred for a broader compatibility with
the tools.
You can find it here
I looked through all those answers and found nobody mentioned a child component can pass a style CSS in from its parent.
In component ts file, you can use this:
#Input() styles: any = {};
In component html file, you use this:
[ngStyle]="styles"
in parent, you use this :
<yourComponent [styles]="{backgroundColor: 'blue', 'font-size': '16px'}">
Please see more details here: Best way to pass styling to a component
In this way, we didn't break encapsulation, which is one of those most important Object orientation principles
Use ::ng-deep with caution. I used it throughout my app to set the material design toolbar color to different colors throughout my app only to find that when the app was in testing the toolbar colors step on each other. Come to find out it is because these styles becomes global, see this article Here is a working code solution that doesn't bleed into other components.
<mat-toolbar #subbar>
...
</mat-toolbar>
export class BypartSubBarComponent implements AfterViewInit {
#ViewChild('subbar', { static: false }) subbar: MatToolbar;
constructor(
private renderer: Renderer2) { }
ngAfterViewInit() {
this.renderer.setStyle(
this.subbar._elementRef.nativeElement, 'backgroundColor', 'red');
}
}

Resources