How do I format a new line in a SASS (Syntactically Awesome Stylesheets) file? [duplicate] - html

I love Sass's indented syntax (as opposed to SCSS, which is whitespace agnostic and uses brackets and semicolons). I think it's much cleaner.
There's one issue I have with it. If I have a really long line, there's no way to split it into multiple lines (obeying the 80 character limit, for example)
Take this example of a really long mixin declaration, first written in SCSS.
#mixin col($cols, $mleft: 0, $mright: 0, $include-margin: false, $border: 0,
$pleft: 0, $pright: 0, $include-padding: true, $extra: 0,
$clear: false, $lead: true, $container: false) {
color: red;
display: block;
}
I'm able to split up one long declaration in to multiple lines. With the indented syntax, I don't think there's a way. I have to put the declaration on one line, which is way less readable.
#mixin col($cols, $mleft: 0, $mright: 0, $include-margin: false, $border: 0, $pleft: 0, $pright: 0, $include-padding: true, $extra: 0, $clear: false, $lead: true, $container: false)
color: red
display: block
Is there some way I don't know of? :(

Multiline is not supported by sass. Reading the doc, there is one exception, when it comes to multiple css selectors like in this example:
.users #userTab,
.posts #postTab
width: 100px
height: 30px
Read the doc here: http://sass-lang.com/docs/yardoc/file.INDENTED_SYNTAX.html#multiline_selectors
So, sadly: There is no possibility to get multi-line support for an argument list in sass.

First: do not create mixins with so many arguments. Divide it to many small mixins or insert some similar arguments as arrays (Sass have data maps for it).
Second: you can use temporary variables just for readability of your large code.
For example:
=mixin($argument)
body::before
content: $argument
$v1: 'foo-'
$v2: 'bar-'
$v3: 'baz.'
$var: $v1+$v2+$v3
+mixin($var)
This will get you mixin with all your $v# strings joined to one $var.
body::before {
content: 'foo-bar-baz';
}
If someone knows better way to join many strings into one in indented Sass syntax, I will be happy to know. Because I write complex gradients and inline generated SVG with this.

Related

Can a sass selector contain a '%' character?

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.

Jade: Best practice with classes and ids

I've searched for a while now, but I couldn't find an answer.
To create a div container with a class or id in Jade you can write:
.foo
#bar
or
div.foo
div#bar
Another thing is multiple classes:
div.foo.bar
or
div(class="foo bar")
What's best practice or is it just personal preference?
It is just a shorthand notation. Nothing wrong with it, just more readable for users who are unfamiliar with the shorter syntax to implicitly show that you are creating a div.
In some cases, using a shorthand syntax however causes the interpreter to perform better, because it works a bit different under the hood.
I'm not familiar with how Jade works, but maybe using just the dot notation saves some work behind the scenes, whilst using the more explicit instructions takes more time to parse.
Same as something similar in css:
border-style: solid;
border-width: 1px;
border-color: red;
/* shorthand */
border: 1px solid red;
Or javascript:
var foo;
if (true){
foo = "bar";
} else {
foo = "not bar";
}
// shorthand
var foo = true ? "bar" : "not bar";
var x = x + 1;
// shorthand, and might uses the processor or engine differently
var x += 1;

Why won't this LESS css sizing mixin compile?

I'm trying to create a mixin that'll take two parameters and output sizing in px and rem. This is the code:
.sizing (#cssProperty; #sizeValue) {
#cssProperty: ((#sizeValue * #basefont) * 1px);
#cssProperty: (#sizeValue * 1rem);
}
Usage would be like:
h2 {
.sizing(font-size; 1)
}
Which should output (depending on what basefont size is defined):
h2 {
font-size: 12px;
font-size: 1rem;
}
But simpLESS won't compile it, and says there's an error in these two lines:
.sizing (#cssProperty; #sizeValue) {
.sizing(font-size; 1);
What am I doing wrong? Is it because of the variable property names?
Just noticed that you are trying to use variables as property names instead values which is not supported by less.
There is a hack highlighted in this answer as workaround:
How to pass a property name as an argument to a mixin in less
.mixin(#prop, #value) {
Ignore: ~"a;#{prop}:#{value}";
}
LESS does not allow to use a variable as a CSS property name.
In your code above #cssProperty: ((#sizeValue * #basefont) * 1px); is actually a definition of the new #cssProperty variable and not a CSS property: value statement, hence it produces no CSS output.
There's a workaround for what you want to achieve though, see 14868042, 18558368 etc...

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