TailwindCSS focus + placeholder in CSS file - tailwind-css

Is it possible to move the class focus:placeholder-gray-600 from the HTML into a CSS file?
From the following HTML
<input class="focus:placeholder-gray-600" type="text">
And I'd like to have
<input class="my-class" type="text">
#styles.css
.my-class {
...
}

Yes you can do that with tailwind css, but not with just css files.
You would need to process your css files with PostCSS and then follow the steps outlined in the documentation under Extracting CSS components with #apply
The basic idea is, to use the tailwind-provided #apply postcss directive:
<style>
.my-class:focus {
#apply placeholder-gray-600;
}
</style>
Note, that the focus aspect has to be used like in "regular" css with the pseudo selector in the class declaration instead of doing this:
/** INVALID **/
.my-class {
#apply focus:placeholder-gray-600;
}
See also this note from the docs:
Note that variants like hover:, focus:, and {screen}: can't be applied directly, so instead apply the plain version of the utility to the appropriate pseudo-selector or media query.

Related

How to lower mat-icon with input in angular material?

This is my code:
<mat-form-field>
<input type="tel" matInput placeholder="Home">
<mat-icon matSuffix svgIcon="home" class="mdi-icon"></mat-icon>
</mat-form-field>
And this is the result:
As it is seen icon is to high and I want to lower it to decrease the distance between the bottom line and the icon. I tried:
.mdi-icon {
margin-bottom: -5px;
}
But it didn't help. Could anyone say how to do it?
For the CSS to have any effect on a child component you first need to first get around view encapsulation. View encapsulation will add a unique attribute to all of your HTML elements within the template, something like _ngcontent-nvb-c74="", then it will append that identifier to all of your CSS like [_ngcontent-nvb-c74]. That is how the CSS of one component does not affect others.
We need to make the CSS global. So, we need to use a unique selector or else your CSS will leak into other components. I would use the component name personally. I'm using app-my as an example selector for the component MyComponent. So in all three cases your CSS will look like:
app-my .mdi-icon {
...
}
Your options to get around View Encapsulation are:
1. Disable View Encapsulation for the component - not usually recommended
#Component({
...
encapsulation: ViewEncapsulation.None,
})
export class MyComponent {}
This makes all of the CSS in that component global, not great if you want view encapsulation in other areas of your component.
2. Put your CSS in styles.css
Any CSS in this file is global by default.
3. Create a new global style file for this component
Something like my.component.global.css
After creating this file you need to add it to the styles array in angular.json. Any CSS files in this array are applied globally, styles.css is the only one by default.
angular.json
"styles": [
"src/styles.scss",
"src/app/my.component.global.css"
],
If you're using scss, you can import this file into styles.scss instead of adding it to the styles array.
Now for actually moving the icon, I'm just using the non-svg icon but it should work the same
<mat-form-field>
<input type="tel" matInput placeholder="Home" />
<mat-icon class="mdi-icon">home</mat-icon>
</mat-form-field>
I removed matSuffix
app-my .mdi-icon {
position: absolute;
right: 0;
top: 5px;
}
In some cases you will be overriding other css already present in the child, to do that, you may need to increase the specificity by repeating a class (not necessary in this case)
app-my .mdi-icon.mdi-icon.mdi-icon {
position: absolute;
right: 0;
top: 5px;
}

ng-deep not working when switching between components?

I have 2 components A B , in each component's css file I have a ngx-bootstrap datepicker which i need to customize ( align ).
In A component css file I have
::ng-deep .bs-datepicker {
margin-top:-100px
}
In B component css file I have
::ng-deep .bs-datepicker {
margin-top:-80px
}
When I go to component A and inspect element it shows A's css file, which is what i want,
But when go to component B and then come back to component A , It shows B's Css file in Component A, so it shows margin-top:80px in Component A.
How do I segregate styling between these two components without one affecting the other when i switch from one component to other?
You can wrap the bs-datepicker in a container and use it name to capture
::ng-deep .container-one * .bs-datepicker {
margin-top:-100px
}
::ng-deep .container-two * .bs-datepicker {
margin-top:-80px
}
and in HTML files:
<div class="container-one">
<input type="text" bsDatePicker>
</div>
<div class="container-two">
<input type="text" bsDatePicker>
</div>
Those will have different styling
I also recommend stopping using ::ng-deep to prevent unexpected behaviours (just like you had in this situation).
The approach above will also work on styles.scss file without the ::ng-deep with the correct angular.json configuration

Tailwind CSS how to style a href links in React?

For some reason, tailwind seems to have removed the "blue" and "underlined" part of http links.
How do I get this functionality back?
For example, in my React code, i have:
return (
<a href={v.url}>{v.alias}</a>
);
but this link shows up like normal font, and there's no underline. there's also no notion for browser to remember or hover different color on the link.
Tailwind's Preflight functionality will remove all of the browsers' default stylings for most elements, giving you a clean basis to start from, to make cross-browser styling more consistent.
You need to re-add the styles you wish, for example:
className="underline text-blue-600 hover:text-blue-800 visited:text-purple-600"
or:
a {
#apply underline text-blue-600 hover:text-blue-800 visited:text-purple-600
}
EDIT: It appears that this extra configuration is not needed with Tailwind 3 (at least as tested with 3.1.1). It may still be needed if you use Tailwind 2. See Patrik's comment below for an example.
As Luke correctly explained, Tailwind's Preflight removes all the browser defaults. You'll have to add the styling yourself:
className="underline text-blue-600 hover:text-blue-800 visited:text-purple-600"
However, you can't just use visited: with text-purple-600 without some configuration (at least with Tailwind 2. I'm not familiar with older versions). You'll also need to add the following to your Tailwind config at your project root:
// tailwind.config.js
module.exports = {
// ...
variants: {
extend: {
textColor: ['visited'],
}
},
}
That way, Tailwind will make all the classes with visited: available for use with all the text color classes.
You can learn more about enabling extra variants in the Tailwind docs.
So the other answers correctly have pointed out that preflight and/or base will reset the components, but you can also use the #layer and #apply directives to apply classes to elements in bulk.
#layer gives you a bucket to put things into, the ones currently available in Tailwind would be like base, components, and utilities.
For example, if you wanted to set all links to blue and underline, you could do the following:
#layer base {
a {
#apply text-blue underline
}
}
The linked examples show how you could group the elements to make a meta-class for styling buttons consistently.
#layer components {
.btn-blue {
#apply bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded;
}
}
I have to disagree with others here who suggest re-adding the default anchor tag styling as a solution. You can do this, but one annoyance of working with normal anchor tags is when you wrap a button in an anchor tag, the styling cascades into the text on the button, which is super annoying.
Instead, I would suggest creating your own utility class that applies these styles instead of changing the styles for all <a> tags. For example:
.hyperlink {
#apply text-blue-600 underline
}
.hyperlink:visited {
#apply text-purple-600
}
Now, use that class explicitly when you want it rather than applying it no matter what.
<a class="hyperlink" href="/foo/bar">Text link</a>
<button>Style-Free Button!</button>
If you are using #apply note that the states (like hover) cannot be added in-line like you would pass to a class.
a {
#apply underline text-blue-600 hover:text-blue-800 visited:text-purple-600
}
They need to be broken out and matched to the css states like this:
a {
#apply underline text-blue-600
}
a:hover {
#apply text-blue-800
}
a:visited {
#apply text-purple-600
}
tailwind.config.js
extend: {
content: {
'externalLink': "url('images/icons/icon-external.svg')",
}
},
In css
a {
#apply underline underline-offset-4 decoration-1 decoration-primary;
&:hover {
#apply no-underline bg-tertiary/20;
}
&:visited {
#apply text-primary;
}
&[target="_blank"]:after {
#apply content-externalLink inline-block ml-1 mt-1;
}
}

How to load different .css files on different components of a react application?

I have two .jsx files that represent their respective components.
The first one is, Blog.jsx
import React from "react";
import '../assets/css/blog.css';
export const Blog = () => (
<div>
<h1>Hello Blog</h1>
</div>
)
With its respective CSS file, blog.css
div { background: #ff481f; }
and the second one is, Landing.jsx
import React from "react";
import '../assets/css/landing.css'
export const Landing = () => (
<div>
<h1>Hello Landing</h1>
</div>
)
With its respective CSS file, landing.css
div { background: #86ff2b; }
I have added routing and called instances of those two components on the App.js file which is the default file of a React application. After running the application, when navigated to components, I faced a problem that the background color is the same for both of the components (It loads landing.css only and never changes).
How can I fix that problem that each component only uses its respective .css file and loads it?
By default webpack and other build tools will compile all CSS files into one, even if css was imported in separate JSX files. So you can't use different CSS files and expect you don't affect on another part of page.
You have some options:
Use BEM for naming class names.
Use cssModules. In this case elements will have their own css class name and styles will not affect any other elements except if you use :global selector.
css-module
Using html tags as css selectors is a bad practice (because there is the behaviour you describe).
You should use only css classes or inline styles (using id's is another bad practise, id's have high priority).
div {
width: 20px;
height: 20px;
}
#id {
background: red;
}
.class {
background: green;
}
<div id="id" class="class"></div>
In case using css classes there is the same problem (when you have two similar classes). And this case is decided using css modules (set of rules of building) or you can use css-in-js (external library) which has its pros and cons. Also you can use BEM (methodology) and if your application is not big you can avoid this trouble.
css modules will add to your classes random hash and instead .my-awesome-class-name you will get .my-awesome-class-name-dew3sadf32s.
So, if you have two classes .class in the first file and .class in the second file in the end you will get two classes .class-dew23s2 and .class-dg22sf and you styles will resolve as expected.
css-in-js is a similar way except you should write your styles using javascript with some profits like including only those styles that are needed at the moment (what you are looking for right now) and several others.
You can code using pure css / scss / postcss / etc but many companies already choose between css modules and css-in-js.
BEM is just naming conventions for your class names.
And lastly - if you use inline-styles using react you should remember:
{} is constructor of object and {} returns new object on every call, it's mean if you write something like:
class MyAwesomeComponent extends Component {
render() {
return <div style={{color: "red"}}></div>;
}
}
or
class MyAwesomeComponent extends Component {
render() {
const divStyles = {color: "red"};
return <div style={divStyles}></div>;
}
}
div will re-render every time your render will call because div takes new prop.
Instead, you should define your styles (for example) in outside of your class:
const divStyles = {color: "red"};
class MyAwesomeComponent extends Component {
render() {
return <div style={divStyles}></div>;
}
}
Don't define your css using HTML tags because it will affect your entire application.
use className,id or inline styling.
like- App.css
.myApp{ color: red;}
#myApp2{ color: blue;}
App.js
import './App.css'
<div className="myApp">color changed by className</div>
<div id="myApp2">color changed by id</div>
<div style={{color:'red'}}>color changed by inline object styling</div> // inline styling
This is not the best solution if you are looking forward to improve yours css imports/loads.
However could be the best solution if you dont want to go in deep in css, resolve the problem fast and keep working with HTML tag.
You can add a div for each component, define an Id for the div and wrap the component. Afterwards in the component's css fies you are going to define all the styles starting with the #id so all the css classe or HTML tag will affect just the corresponding component.
//App render in root
ReactDOM.render(
<App />,
document.getElementById('root')
);
//App
function App(props){
return [
<Blog />, <OtherComponent />
]
}
//Blog component
function Blog(props){
return <div id="blog">
<h1>I am Blog</h1>
</div>
}
//Other component
function OtherComponent(props){
return <div id="otherComponent">
<h1>Im am other component</h1>
</div>
}
/* blog.css*/
#blog h1{
color:yellow;
}
/* otherComponent.css*/
#otherComponent h1{
color:green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Nesting SCSS Rules in VueJS Modules

How can I handle nested SCSS rules, which expand on a base style, when dealing with the CSS Modules to import styles to the local component?
In my case, I have the following two SCSS files:
icon.scss
.my-icon {
// base styles for an icon
}
button.scss
.my-button {
...
.my-icon {
// special styles when an icon is in a button
}
}
Which I then import into their respective components:
MyIcon.vue
<template><i class="my-icon" /></template>
<style lang="scss" module>
#import '/path/to/icon.scss'
</style>
MyButton.vue
<template><button class="my-button"><slot /></button></template>
<style lang="scss" module>
#import '/path/to/button.scss'
</style>
The trouble is that the nested .my-icon class, in 'button.scss', generates a different hash ('._2XJ5') than the root .my-icon class, in 'icon.scss' (._2UFd). So, when I attempt to embed an icon into a button I get an output that looks like this:
<button class="._3S2w"><i class="._2UFd" /></button>
Which is correct, but the "special styles" for an icon in a button are not applied, because that class was generated as a different hash.
How do I make sure the hash value for '.my-icon' always comes out the same?
Somewhere, hidden deep in the Vue loader, the documentation talks briefly about how you can escape the scoped styling. The solution is to use a /deep/ selector, which is preprocessed by scss to give everything behind it no hash. There is something similar in normal css, but it is somewhat unrelated.
Say we have our my-button component and want to style my-icon classes inside it, we can do the following:
<template>
<div>
<slot></slot>
</div>
</template>
<style lang="scss" scoped>
/deep/ .my-icon {
background: red;
}
</style>
The following should generate something like the following. It is still scoped within your component, but .my-icon does not have to be part of your component. In this case, it could be inside the slot for example.
[data-v-f3f3eg9] .my-icon {
background: red;
}

Resources