Tailwind CSS how to style a href links in React? - css

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

Related

TailwindCSS focus + placeholder in CSS file

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.

CSS Modules & ReactJS: Parent and child CSS classes in different components

So I am building a react application and have a quick question. If I have two separate components:
and
with CSS classes navigation.css and navigationLogo.css respectively. In navigation.css I have a class named .main and in navigationLogo.css I want to have a class like so:
.main .main_in_logo {
color: red;
}
But with CSS Modules I am unable to do this, any ideas on a work around?
I just feel that the explanations here are not complete enough. In css you do .parentSelector .childSelector in order to select the child. The same rule is for css modules, but in your html/jsx you should add to the parent and the child the relevant className -> styles.parentSelector , styles.childSelector.
<div className={styles.container}>text</div>
This way you can have in your css something like:
.banner .container{
background-color:reb;
}
.banner .container{
background-color:blue;
}
Sometimes you use libraries and you want to change something somewhere down the DOM inside the library and you can't change its source code. In this case you can use the :global like this:
.parentElement :global(div)
.parentElement :global(#some-lib-element-selector)
I was looking for the same problem and didn't find the solution here, maybe because the post is 3 years old. The accepted answer is, in my opinion but not mine only, not scalable.
I don't really know if this is something new, but I found out what I would do in vanilla CSS adapted to CSS modules.
Here is what I did and fully suits my needs:
/* parent.css */
.main {
...some CSS...
}
/* logo.css */
#value main from "./parent.css";
.logo {
...some CSS...
}
.main .logo {
color: red
}
Here, we are using #value, which is a CSS modules variable and allows us to bind with another file to build a selector including the final name of the parent "main".
As strange as it looks to me, it took some time to find out about this solution, I hope this will save some time and help other people!
Why you need to create .main .main_in_logo - the main idea of styles with parent elements its not to broke your css with other styles in the future. But its impossible with css modules, because your styles will be unique forever.
But even you really need it you can use global css for these 2 components - documentation about global css for react-css-modules.
The child component should not have a css rule that is dependent upon the parent css classname.
the child should just be:
.main_in_logo { color: red; }
If you need to define styles that involve both parent and child, then the easiest way is to define the styles completely in the parent:
/* navigation.css */
.main .main_in_logo {
color: red;
}
Then have the parent pass the css class to the child and tell the child to use it:
// Navigation.js
<NavigationLogo className={navigationCss.main_in_logo} />
// NavigationLogo.js
<div className={"foo " + this.props.className}>stuff</div>
You don't need to be specify which child class you are referring to when using CSS modules in ReactjS.
so doing:
.main_in_logo {
color: red;
}
will be enough in the stylesheet.
I ended up using CSS the normal way but with BEM convention.
I mean after all, what the CSS modules do is adding the [this_name].module.css to your css classes anyway. If you typed it correctly in the first place, there's no need of using this. It's just a new abstract that allow newbies so they can just do stuff without having to worry about class names clashing.
// Main.jsx
import './Main.css'
import Logo from './Logo.jsx'
const Main = () => {
return (
<div className="main">
<Logo className="main__logo" />
</div>
)
}
/* Main.css */
.main {/* do magic */}
.main__logo {/* do magic but for Logo component */}
So maybe you had Logo component like this..
// Logo.jsx
import './Logo.css'
const Logo = () => {
return (
<div className="logo">
<img className="logo__img" />
</div>
)
}
/* Logo.css */
.logo {/* do magic for logo */}
.logo__img {/* do magic for logo's image */}
This feels much more natural.

Apply stylesheet to half a page with shadow-dom?

Can I apply an external stylesheet to a specific div/element with shadow-dom or via any other means? I've heard about shadow-dom and I believe it lets you constrain your styles, but that's about all I know.
Specifically, I want half the page to use bootstrap, and the other half to use MUI or something else. This is just to show how my library works nicely with different themes.
I don't want to modify the CSS in anyway to constrain it to a specific element, nor do I want to use iframes.
Yes, you can apply an external stysheet in a Shadow DOM using the #import url CSS rule.
div.attachShadow( { mode: 'open' } )
.innerHTML = `
<style>
#import url( './external-style.css' )
</style>
<!-- other elements -->`
NB: The #import rule must placed at the top of the <style> element.
You can then manipulate the Shadow DOM like a normal DOM:
div.shadowRoot.appendChild( firstSection.cloneNode( true ) )
If your content is already existing in the normal DOM, you can move it with appendChild(), duplicate it with cloneNode() as in the above example), or reveal it with the help of <slot> element:
div1.attachShadow( { mode: 'open' } )
div1.shadowRoot.innerHTML = `
<style>
:host { display: inline ; background: #cfc ; }
::slotted( span ) { color: red ; }
</style>
<slot></slot>`
<div id=div1>
<span>Hello</span> world
</div>
In the last case you'll need to use the ::slotted pseudo-element to change the style of the original DOM, so maybe you'll have to modify already existing stylesheet. The best solution depends on your use case.

Change style of pseudo elements in angular2

Is it possible to change style of pseudo elements using [style] or [ngStyle] in angular2?
in order to get a blur effect on a div acts like an overlay, and I should set up background-image on pseudo element.
I tried something like
<div class="blur" [style.before.backgroundImage]="'url('+ featuredImage[i] + ' )'">
it didn't work. I also tried this
<div class="blur" [ngStyle]="'{:before{ background-image:url('+ featuredImage[i] + ' )}}'">
You can achieve what you need with CSS variables.
In your style sheet you can set the background image like this:
.featured-image:after { content: '';
background-image: var(--featured-image);
}
After that you can programmatically set this variable on the same element or higher up in the DOM tree:
<div class="featured-image" [ngStyle]="{'--featured-image': featuredImage}">
More about CSS variables here: https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables Note that the browser support is not complete yet.
Also note that you will need to sanitize the url/style using sanitizer.bypassSecurityTrustResourceUrl(path) or sanitizer.bypassSecurityTrustStyle('--featured-image:url(' + path + ')')):
No it's not possible. It is actually not an Angular issue: pseudo elements are not part of DOM tree, and because of that do not expose any DOM API that can be used to interact with them.
Usual approach if you want to deal with pseudo elements programmatically is indirect: you add/remove/change class and in CSS make this class affect corresponding pseudo-element. So in your case you could have one more class that changes necessary style:
.blur:before {/* some styles */}
.blur.background:before {/* set background */}
Now all you need to do is to toggle .background class on the element when you need before pseudo-element to get a background. You can use NgClass, for example.
if you want to add other properties I did it like this:
<div class="progress" [style]= "'--porcentaje-width:' + widthh " ></div>
and the css:
.progress::after {
content: '';
width: var(--porcentaje-width);
}
this worked for me :)
With current versions of Angular 2+ you can use CSS Variables to achieve this as well as sanitizing your input.
In your style sheet define the rule using CSS Variables. A fallback can also be defined as CSS Variables aren't supported by IE.
https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties
.featured-image:after {
content: '';
// Fallback for IE
background-image: url('fallback-img.png');
background-image: var(--featured-image);
}
Rather than bypassing security trust style, you can also sanitize your input with a reusable pipe:
https://angular.io/api/platform-browser/DomSanitizer#sanitize
import {Pipe, PipeTransform, SecurityContext} from '#angular/core';
import {DomSanitizer, SafeStyle} from '#angular/platform-browser';
#Pipe({
name: 'safeStyle',
})
export class SafeStylePipe implements PipeTransform {
constructor(protected sanitizer: DomSanitizer) {}
transform(value: string): SafeStyle {
if (!value) return '';
return this.sanitizer.sanitize(SecurityContext.STYLE, value);
}
}
In your template:
<div class="featured-image" [style.--featured-image]="featuredImage[i] | safeStyle"></div>

Every h2 except for ones that don't have a class?

I'm wondering how can I apply a style to EVERY h2 that DOES have ANY any class attached to it, thus having the effect that the style will NOT be applied on a plain h2..eg..
<h2 class="1"></h2>
<h2 class="2"></h2>
<h2 class="3"></h2>
<h2 class="a"></h2>
<h2></h2>
All the ones with a class should have a style - and just plain h2 should not, (This is a huge site with hundreds of styles)...so any easy way to do this?
There is a method to do it but it's only possible with browsers that support CSS3 :not pseudo class.
h2[class] {
/* Styles for <h2> with a class, regardless of the value */
}
h2:not([class]) {
/* Styles for <h2> without classes */
}
I hope it works!
[Edit] I've made a simple demo for you here - http://jsfiddle.net/fL2sT/
What you're asking for is how CSS works by default.
The correct way to style elements which have no specific class assigned to them is to style the base element, as Ahsan demonstrated above. I don't know why he got downvoted.
h2 { property: value; }
Note that if H2 elements do have classes assigned to them, then that styling may override your base style.
So if you have: h2 { color:#333; font-size:2em; } as your base style, and then apply class="myClass" to it where: .class { color: #000; }, then the base style's color will be overriden (but not the font size). This is the cascade in Cascading Style Sheets.
Another way is to target them conditionally:
div#nav h2:first-child { property:value; }
which gives you contextual control, but again, class assignment will always override base styling, and may also override context targeting if the class application has higher specificity.
Why not simply use
h2[class] { ... }

Resources