Can a sass selector contain a '%' character? - html

I have a variable that contains a string value in the form of some percentage eg. '10%' I want to use that value to build a class name to add to my html element if the percentage is anything above '0%'. I thought this would be easy using a sass loop but I can't seem to get the class name constructed correctly.
I thought it would look something like this.
#for $i from 1 through 100{
.highlight-#{$i}% {
// styling
}
}
.highlight-0% {
// styling
}
I have tried several variations:
.highlight-#{$i + '%'} { // styling }
.highlight-#{$i}${'%'} { // styling }
I don't know if this is even possible since '%' may be reserved.
I am adding the html just in case someone can suggest a way to remove the % in there. This is what I would like to be able to do:
<tr><td class="pad-10 highlight-${publisher.numViewsPercentage}" align="center">${publisher.numViewsPercentage}</td></tr>

Not only is % a reserved character in Sass, the bigger issue is it's not an allowed character in CSS selector names. So even if you could make Sass compile the resulting class names won't be valid and won't work.
For the most part selector names need to use only letters, numbers, underscore and hyphens.
.nopercent {
color: red;
}
.percent% {
color: red;
}
<div class="nopercent">
An element withOUT a percent sign in the class.
</div>
<div class="percent%">
An element with a percent sign in the class.
</div>

% is a placeholder character in SASS since version 3.2.
You should just use it for "invisible" extendeds.

Related

Is possible create a css class name with numbers "from-to"?

I need to have 3 classes as follow:
.class-4, .class-5, .class-6 {
color: pink;
}
And it works perfectly.
Let's say I need the same but for 100:
.class-4, .class-5, .... .class-100 {
color: pink;
}
Is there anything similar to this or any other way to do this which I can use.
.class->3<101 {
color: pink;
}
To get the same result without writing 97 times the class and the comma?
There is nothing in pure CSS which will do this, but you could use JavaScript to create a stylesheet for you which has all that tedious repetition created automatically.
In this snippet you say what the ends of the class ranges are and what styling is to be put in each of the ranges.
If there is a range which you don't want to alter then you still need to include it but make its styles string just an empty string.
The snippet runs through each of the ranges creating the relevant style sheet entries and puts them in a style element in the head element of the document.
A few fairly random divs are shown here just to test that we are hitting the right ranges.
const rangeEnds = [4, 20, 35, 41, 48, 100];
const styles = ['color: pink;', 'color: red; background-color: black;', 'color: green;', 'color: yellow;', 'color: blue;', 'color: black; background: pink;'];
let lastRangeEnd = 0;
const styleEl = document.createElement('style');
for (let i = 0; i < rangeEnds.length; i++) {
for (let j = lastRangeEnd + 1; j < rangeEnds[i]; j++) {
styleEl.innerHTML += '.class-' + j + ',';
}
styleEl.innerHTML += '.class-' + rangeEnds[i] + '{' + styles[i] + '}';
lastRangeEnd = rangeEnds[i];
}
document.querySelector('head').append(styleEl);
<!doctype html>
<html>
<head>
<title>Classes</title>
</head>
<body>
<div class="class-1">ABCD</div>
<div class="class-19">ABCD</div>
<div class="class-21">ABCD</div>
<div class="class-40">ABCD</div>
<div class="class-41">ABCD</div>
<div class="class-48">ABCD</div>
<div class="class-100">ABCD</div>
</body>
If all elements will have the same property which is {color:pink}
You can create only one class (lets call it .pink)
.pink {
color: pink;
}
and then you can simply give your elements the .pink class.
One of class attribute's main purpose is to define a shared style reference name. It is rather not a very good practice to want to reference multiple class references and let them share the same styling.
The best way to get around this is to have a common class attribute name YourClassName. This way, any element you want the styling applied to can have that class appended to its class attribute through element.classList.add(YourClassName) with JS. And, that would solve all the hussle of having to worry about putting multiple classe names and I cannot think of any 1 situation that would force you to declare each element class separated by commas provided that they are to receive the same styling.
The OP asks if it’s possible to have a ‘number range’ (array) at the end of CSS classes that shares the same name, but ending on 1, 2, 3, etc.
As #zer00ne pointed out; You can target multiple classes with one "class". When defining your class selector - leave out the numbers, but make the class name unique.
So, if the class names are i.e. my-row-class-1, my-row-class-2, etc., write the selector like this;
[class^="my-row-class-"] {
color: pink;
}
Pro tip: Instead of using class^= selector, it's possible to do this for id^= as well - and more. Check out the MDN web docs for more info.

Razor - How to store html special character in variable

On my html page, I want to make a list from a collection of entries in my model. However, some of those entries may be null, and in that case I want to have an empty list item, like so:
Something
Something else
More stuff
I do that by inserting a non-breaking space character. (regular whitespace won't generate empty list items) Here's a code snippet:
<ul>
#{
foreach (var x in Model.Entries)
{
var rayon = x.Rayon ?? " ";
<li>#rayon</li>
}
}
</ul>
Sadly, this does not work because it instead pastes verbatim.
And removing the quotation marks, and/or adding #: at the start, won't compile.
What can I do?
You can use Html.Raw.
use like this
<li> #(Html.Raw(rayon)) </li>
Instead of " " just give a blank string:
var rayon = x.Rayon ?? string.Empty;
In fact, I think you can even just scrap that variable assignment together and just use x.Rayon as-is - a null value should have the same effect
<ul>
#{
foreach (var x in Model.Entries)
{
<li>x.Rayon</li>
}
}
</ul>
Update:
Both above work for me. So, if still not working, it looks to be down to CSS/styles on your ul.
e.g.
OK, I think this is down to CSS/styles on the ul that you have then (both above work fine for me). e.g. the following CSS would hide empty li elements:
ul li:empty {
display: none;
}
So, check out your CSS.
If you don't want to change the existing style, you could add an extra class to your CSS and apply that for just this instance.
i.e.
CSS:
ul.show-empty-li li:empty{
display:list-item;
}
HTML:
<ul class="show-empty-li">
...
</ul>

Is it possible to replace a char by another with CSS?

My goal is to replace the display of _ by a blank space in my HTML document:
ex:
hello_world
should be
hello world
Possible Solutions:
Would be to create a
FONT that uses blank inside the _ character
Still looking for it!
Can this be done with CSS?
It is important that we do not modify the original string (we keep the _ character), but we simply display a blank space instead.
Regards
I think this is possible in CSS for a one-off kind of thing:
<span class="replace-me">hello_world</span>
.replace-me{
display:none;
}
.replace-me:after{
content:'hello world';
}
But I'm guessing that's not exactly what you want.
Otherwise, to replace all instances in JS:
document.body.innerHTML = document.body.innerHTML.replace('_', ' ');
You'll likely have to get a little more fancy with the regex but you could parse the page for underscores and wrap them in a <span>. Then use a pseudo element that has it's content set to a single space to replace the wrapped underscore.
<p>
Some_content with_underscores_going_on.
</p>
span:after {
font-size: 16px;
content: ' ';
}
span {
font-size: 0;
}
// jQuery
var f = $("body");
f.html( f.html().replace(/_/g,"<span>_</span>") );
jsFiddle: http://jsfiddle.net/h2h1bmyn/1/

Change last letter color

Example code:
<p class="test">string</p>
I want to change the color on the last letter, in this case "g", but I need solution with css, I don't need a javascript solution.
I display the string letter by letter and i cant use static solution.
Everyone says it can't be done. I'm here to prove otherwise.
Yes, it can be done.
Okay, so it's a horrible hack, but it can be done.
We need to use two CSS features:
Firstly, CSS provides the ability to change the direction of the flow of the text. This is typically used for scripts like Arabic or Hebrew, but it actually works for any text. If we use it for English text, the letters are displayed in reverse order to how the appear in the markup. So to get the text to show as the word "String" on a reversed element, we would have to have markup that reads "gnirtS".
Secondly, CSS has the ::first-letter pseudo-element selector, which selects the first letter in the text. (other answers already established that this is available, but there's no equivalent ::last-letter selector)
Now, if we combine the ::first-letter with the reversed text, we can select the first letter of "gnirtS", but it'll look like we're selecting the last letter of "String".
So our CSS looks like this:
div {
unicode-bidi:bidi-override;
direction:rtl;
}
div::first-letter {
color: blue;
}
and HTML:
<div>gnirtS</div>
Yes, this does work -- you can see the working fiddle here: http://jsfiddle.net/gFcA9/
But as I say, it is a bit hacky. And who wants to spend their time writing everything backwards? Not really a practical solution, but it does answer the question.
Use ::after pseudo-element combined with attr() function:
p::after {
content: attr(data-end) ;
color: red ;
}
<p data-end="g">Strin</p>
p::after {
content: attr(data-end) ;
color: red ;
}
<p data-end="g">Strin</p>
Another solution is to use ::after
.test::after{
content: "g";
color: yellow;
}
<p class="test">strin</p>
This solution allows to change the color of all characters not only letters like the answer from Spudley that uses ::first-letter. See ::first-letter specification for more information. ::first-letter applies only on letters it ignores punctuation symbols.
Moreover if you want to color more than the last character you can :
.test::after{
content: "ing";
color: yellow;
}
<p class="test">str</p>
For more information on ::after check this link.
Without using javascript, your only option is:
<p class="test">strin<span class="other-color">g</span></p>
Edit for your fiddle link:
I'm not really sure why you said you didn't need a javascript solution, since you have quite a bit of it already. Regardless, in this example, you need to make only a couple small changes. Change line 10 from
elem.text(elem.text() + contentArray[current++]);
to
if ( current == contentArray.length-1 ) {
elem.html(elem.html() + "<span style='color:red'>"+contentArray[current++]+"</span>");
} else {
elem.html(elem.html() + contentArray[current++]);
}
Note that it's important to use .html() instead of .text() now, since there's actually HTML markup being inserted.
Working fiddle: http://jsfiddle.net/QTUsb/2/
It could be achieved using only CSS and an ::after pseudo-element without any changes in HTML:
.test {
font-size: 16pt;
position: relative;
}
.test::after {
bottom: 0;
color: red;
content: 'g';
position: absolute;
transform: translate(-100%, 0);
}
<p class="test">string</p>
In what way do you "display the string letter by letter"? If you're looping through the characters in a string (variable) you can certainly tell when you're at the last letter and wrap it in a whether doing so on the server side or client side.
Looking at the fiddles attached to another of your questions ...
If this is what you're talking about, you might have to set the .innerHTML of the element instead of the element.text()
From the fiddle at http://jsfiddle.net/SLKEn/ you would change it to something like this
if(current < contentArray.length) {
elem.html(
elem.html() +
(current == contentArray.length-1 ?
'<span class="lastchar">' + contentArray[current++] + '</span>' :
contentArray[current++])
);
}
along with CSS span.lastchar { color: red; }
Update: working fiddle based on your other question.
$(document).ready(function() {
var str=$("span").text();
strArr=str.split("");
for(var key=0;key<=strArr.length-1;key++) {
if(key==strArr.length-1) {
var newEle="<span id='lastElement'>"+strArr[key]+"</div>";
strArr[key]=newEle;
}
}
var newtext=strArr.join("");
$("span").html(newtext);
});
span#lastElement {
color: red;
}
i dont have the ability to comment on an answer thread but i wanted to point out an error in an answer provided by Marc_Alx that otherwise works wonderfully. that solution worked for me only after adding a semi-colon behind the content property... so it looks like content:"ing";
.test::after{
content:"ing";
color:yellow;
}
<p class="test">str</p>

Is there an HTML safe truncate method in Rails?

I have a string of HTML in Rails. I'd like to truncate the string after a certain number of characters not including the HTML markup. Also, if the split happens to fall in the middle of an opening and closing tag, I'd like to close the open tag/s. For example;
html = "123<a href='#'>456</a>7890"
truncate_markup(html, :length => 5) --> "123<a href='#'>45</a>"
the regular truncate function works fine, just pass :escape => false as an option to keep the HTML intact. eg:
truncate(#html_text, :length => 230, :omission => "" , :escape => false)
RubyOnRails.org
*Edit I didn't read the question very carefully (or at all TBH), so this answer does not solve this question... It IS the answer I happened to be looking for though, so hopefully it helps 1 or 2 people :)
There are two completely different solutions both with the same name: truncate_html
https://github.com/ianwhite/truncate_html : This is a gem and uses an html parser (nokogiri)
https://github.com/hgmnz/truncate_html : This is a file you put in your helpers directory. It uses regular expressions and has no dependencies.
You should solve this problem with CSS rather than Ruby. You are doing something that affects the DOM layout, and there is no way to programmatically devise a solution that will work consistently.
Let's say you get your HTML parser gem working, and you find a lowest common denominator character count that will work most of the time.
What happens if you change font sizes, or your site layout? You'll have to recalculate the character count again.
Or let's say your html has something like this in it: <p><br /></p><br /> That is zero characters, however it would cause a big chunk of blank text to be inserted. It could even be a <blockquote> or <code> tag with too much padding or margin to throw your layout totally out of whack.
Or the inverse, let's say you have this 3 ≅ λ (3 ≅ λ) That is 26 characters long, but for display purposes it is only 5.
The point being that character count tells you nothing about how something will render in the browser. Not to mention the fact HTML parsers are hefty pieces of code that can at times be unreliable.
Here is some good CSS to deal with this. The :after pseudo class will add a white fade to the last line of content. Very nice transition.
body { font-size: 16px;}
p {font-size: 1em; line-height: 1.2em}
/* Maximum height math is:
line-height * #oflines - 0.4
the 0.4 offset is to make the cutoff look nicer */
.lines-3{height: 3.2em;}
.lines-6{height: 6.8em;}
.truncate {overflow: hidden; position:relative}
.truncate:after{
content:"";
height: 1em;
display: block;
width: 100%;
position:absolute;
background-color:white;
opacity: 0.8;
bottom: -0.3em
}
You can add as many .lines-x classes as you see fit. I used em but px is just as good.
Then apply this to your element: <div class="truncate lines-3">....lots of stuff.. </div>
and the fiddle: http://jsfiddle.net/ke87h/
You could use the truncate_html plugin for this. It uses nokogiri and htmlentities gems and does exactly what the plugin name suggests.
We had this need in zendone.com. The problem was that the existing solutions were very slow when truncating long HTML documents (MBs) into shorter ones (KBs). I ended up coding a library based in Nokogiri called truncato. The library includes some benchmarks comparing its performance with other libs.
This will help you without any extra effort
raw your_string.truncate(200)
your_tagged_string.truncate(60).html_safe
You can use
truncate(html.gsub(/(<[^>]+>)/, ''), 5)
We can do that with the help of simple_format http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html#method-i-simple_format
html = "123<a href='#'>456</a>7890"
simle_format(truncate_markup(html, :length => 5))
=> "123 456 7890"
You can use the truncate method in combination with sanitize.
truncate(sanitize(html_content), length: 100, separator: '</p>', escape: false)
This will truncate your HTML using the separator but it can produce HTML without closing tags. To fix this we can use the sanitize method again, which will clean the HTML and add the missing tags.
sanitize(truncate(sanitize(html_content), length: 100, separator: '</p>', escape: false))
Solving this problem from the client side:
view:
<script>
$(function() {
$('.post-preview').each(function() {
var tmp_height = $(this).innerHeight();
if ((tmp_height > 100) && (tmp_height < 200)) {
$(this).addClass("preview-small");
}
else if (tmp_height >= 200) {
$(this).addClass("preview-large")
}
else {
//do nothing
}
});
});
</script>
css
.preview-small {
height: 100px;
overflow: hidden;
}
.preview-large {
height: 200px;
overflow: hidden;
}