Template literal not working correctly with Tailwind CSS - css

I am passing in a Hex Colour into a prop and attempting to set the background of an element with it. Here is my code:
let cardColourRGB: string;
if (cardColour) {
cardColourRGB = "[" + cardColour + "]";
console.log(cardColourRGB);
} else {
cardColourRGB = "white/50"
}
In the return function:
<div className={`bg-${cardColourRGB}`}></div>
Passing in some colours work, but others don't. For example, passing in #AAA32E as the prop does not set the colour, but setting the colour directly works:
<div className={`bg-[#AAA32E]`}></div>
Why could this be?

According to the official documentation of the tailwind.css it is not preferred to have such classNames
As document says:
The most important implication of how Tailwind extracts class names is that it will only find classes that exist as complete unbroken strings in your source files.
If you use string interpolation or concatenate partial class names together, Tailwind will not find them and therefore will not generate the corresponding CSS:
Don't construct class names dynamically
<div class="text-{{ error ? 'red' : 'green' }}-600"></div>
Instead, make sure any class names you’re using exist in full
<div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
So , for your case, use the following code:
<div class="{{ cardColour ? 'bg-[#AAA32E]' : 'bg-white-50' }}"></div>
Hope it helps!

TailwindCSS doesn't allow you to generate classes dynamically. So when you use the following to generate the class…
`bg-${cardColourRGB}`
…TailwindCSS will not pick that up as a valid TailwindCSS class and therefore will not produce the necessary CSS.
Instead, you must include the full name of the class in your source code. You can return the full value like this
let cardColourRGB: string;
if (cardColour) {
cardColourRGB = "bg-[" + cardColour + "]";
console.log(cardColourRGB);
} else {
cardColourRGB = "bg-white/50"
}
where cardColourRGB is your value you are passing .
By doing it this way, the entire string for every class is in your source code, so TailwindCSS will know to generate the applicable CSS.
Read more: https://tailwindcss.com/docs/content-configuration#class-detection-in-depth

Related

Tailwindcss + Nextjs problems with class + variables

Good afternoon, I need help with a big problem I'm having with tailwindcss + nextjs...
So the problem is when it comes to setting the classes, I need to use a variable, the class is set in the css, but the tailwind is not converting the class into a style.
I need it to be like this:
I already tried to set the class as constant, I tried to set the constant both inside the component and in getstaticprops, and none of them worked.
I've tried to set a class within the css itself and it didn't work either.
Tailwind uses regex to find class names, and because of this they need to exist as unbroken strings in your source code. A consequence of this is you cannot use string interpolation the way you're trying to do, as Tailwind will not be able to find the class name.
What you can do instead is map your props to static class names:
const Component = ({pokemon}) => {
const pokemonBgVariants = {
pikachu: 'bg-pokemontype-pikachu',
bulbasaur: 'bg-pokemontype-bulbasaur',
// ...
}
return (
<div className=`[...other classes] ${pokemonBgVariants[pokemon.types[0].type.name]}`></div>
)
}

Is there a better way to do this in handlebars?

Im using handlebars to spit out some static pages using a partial like so:
{{> component/card size="small" title="Card Title" }}
Now depending on the "size" of the card required, i need to set some different tailwind classes. Im currently doing it like so, but there must be a better way? Adding the class to the container and writing css is not an option.
{{setVariable "additionalHeadingClass" "text-5 md:text-6 mb-4"}}
{{#ifEquals size "small"}}
{{setVariable "additionalHeadingClass" "text-4 mb-1"}}
{{/ifEquals}}
{{#ifEquals size "large"}}
{{setVariable "additionalHeadingClass" "text-4 sm:text-5 md:text-8 mb-4"}}
{{/ifEquals}}
<h3 class="text-primary font-bold {{#root.additionalHeadingClass}}">{{title}}</h3>
and heres the helper im using:
Handlebars.registerHelper("setVariable", function (varName, varValue, options) {
if (!options.data.root) {
options.data.root = {};
}
options.data.root[varName] = varValue;
});
My opinion is that there is too much code in your template for what it actually does. Despite the intimidating number of lines, we really just want to map a size to a string of class names. I would also advise against the setVariable because I find it harder to think about when we creating a side-effect by manipulating a variable on our context object. I would much prefer a more functional-style helper, where we just give it the size and it returns the class names string.
I would create such a helper using a simple switch:
Handlebars.registerHelper('additionalClasses', function(size) {
switch (size) {
case 'large':
return 'text-4 sm:text-5 md:text-8 mb-4';
case 'small':
return 'text-4 mb-1';
default:
return 'text-5 md:text-6 mb-4';
}
});
And then we may reduce our template to the much simpler:
<h3 class="text-primary font-bold {{additionalClasses size}}">{{title}}</h3>
I have created a fiddle for reference.

Applying css to some part of typescript variable through interpolation in Angular

Let's say I have a variable named data in app.component.ts which is of type :string.
In app.component.html I am showing the value of data to the UI using string interpolation like {{data}}.
Now my question is while displaying the value in a UI, I need to apply some css to some specific letters present in a data variable.
For example:
app.component.ts
data : string = "stack overflow"
app.component.html
<p>{{data}}</p>
How to highlight the background color of the word overflow using css?. And I hear that Pipes can be used to modify the value. But here I am in a need of applying css.
And one more constraint is there, initially the value will be displayed to the browser; the word to be highlighted will be coming from input box.
You could use something among the lines of:
.ts
highlightKeyWord(sentence: string, keyWord: string) {
sentence = sentence.replace(keyWord,
`<span style="background-color: #35a5f8;">${keyWord}</span>`);
return this.sanitizer.bypassSecurityTrustHtml(sentence);
}
.html
<p [innerHTML]="highlightKeyWord('hello world', 'world')"></p>
One solution is use pipe to extract given word into separate <span> elements:
#Pipe({
name: 'letterByLetter'
})
export class LetterByLetter implements PipeTransform {
transform(value: string): string {
return value
.split('')
.map((letter) => {
return `<span>${letter}</span>`;
})
.join('');
}
}
Then in component there is possibility to use the pipe in this way <div [innerHTML]="data | letterByLetter"></div>. Notice i've used innerHtml but you can use DomSanitizer instead - which should be better)
After that you are able to decide how the span element should looks. You can set either the class or style directly.
Good luck!

How to add colors to a string in typescript in angular 5

I am trying to display my data in Green color I tried with different methods but still it is not getting populated.
if(typeof(this._serverList)!="undefined"){
var apparr=this._ApplicationList.find(x=>x.appNm==app);
let strlist1=this._serverList.filter(i=>i.envId==envId&&i.appId==apparr.appId).map(x=>x.serverName);
if(typeof(strlist1)!="undefined"){
strlist1.forEach(line=>{
if(line!="")
line.fontcolor("green"); //HERE IS PROBLEM, NOT POPULATING
list+='.'+line+'\n';
});
}
return list;
}
Your problem is using the fontcolor() method - that's old and won't work in HTML5:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fontcolor
If you are rendering the HTML properly from this string, then you should be able to easily achieve this by just assigning some hardcoded HTML to it (that's all fontcolor() does). So instead of doing line.fontcolor(color), you could just replace that line with:
line = '<p style="color: #000">' + line + '</p>
Or use template strings, etc.
document.getElementById('red-text').innerHTML = '<p style="color: red">hello!</p>';
<div id="red-text"></div>

Is it possible to apply dynamic style as string in Angular?

I have a <span> that I want to apply dynamic style to.
Style is stored in a css-like string variable and can be arbitrary e.g.
myStyle = 'color: white; font-weight: bold;'
or
myStyle = 'background-color: red;'
I expected it to work like
<span style="{{myStyle}}">
but it didn't.
I tried different options but none seem to work for me for different reasons:
I can't put styles in a .css file and use class names because style is coming from server in the form of aforementioned string
Using [style.color] etc. doesn't suit me because I don't know what the style can be
Using [ngStyle] doesn't suit me because it expects object like {'color': 'red', 'font-weight': 'bold'} and I only have string
The reason I have a style stored in a string is because I need to apply it in HTML generated on the server where I simply pass that string to a placeholder variable in a velocity template.
I am almost confident that it can't be done the way I want but probably I am overlooking some solution.
All you need is DomSanitizer and bypassSecurityTrustStyle
Component side :
import { DomSanitizer } from '#angular/platform-browser';
constructor(private doms : DomSanitizer) {}
newStyle = 'background-color:red';
safeCss(style) {
return this.doms.bypassSecurityTrustStyle(style);
}
Template side :
<p [style]="safeCss(this.newStyle)">
Start editing to see some magic happen :)
</p>
WORKING DEMO
Angular provides the DomSanitizer service which can convert strings into style objects. I think this is exactly your case.
constructor(private sanitizer: DomSanitizer) {
}
sanitizeStyle() {
return this.sanitizer.bypassSecurityTrustStyle('background-color: red');
}
<span [style]="sanitizeStyle()">
I think I will go the way of converting the incoming css string into a style object and then applying it to <span> using [ngStyle]

Resources