Create LESS variable from HTML content - html

I wasn't able to find a thread on this, but if there is one, please let me know!
I want to create and use LESS variables based on the HTML content in a certain tag.
For example, the HTML would be something like:
<div class="bar">
<span>80%</span>
Blah blah
</div>
And the CSS/LESS would be something like:
#width: '$(".bar > span").text()';
.bar { background: red; width: #width; }
Do I need to convert the variable from a string to an int or float in order for it to be used as such? And if so, how?
Thanks!

I'm not sure if your comment above was mistyped,
"At first, I was trying to to just use a LESS variable for the sizing,
and then set it as the HTML content using the CSS content tag, but it
was working."
You state "but" after which I expected "it was [not] working" (otherwise, I would have expected you to say "and"). That was actually a solution I thought of, but if I am correct, and it was not working for you, then my guess is you were using content incorrectly (directly on the span itself?). The content property is only valid on the ::before and ::after pseudo elements.
So this works like you originally intended (and no need for the span element at all):
LESS
#width: 80%;
.bar {
background: red;
width: #width;
}
.bar:before {
content: '#{width}';
}
CSS Output
.bar {
background: red;
width: 80%;
}
.bar:before {
content: '80%';
}
See Example Fiddle
This will work fine for IE8 (you note supporting that in another comment). Assuming the 80% is not a necessary "content" value (that you want search engines picking up because it is critical data on the page), then using a pseudo element is perfectly fine for such visual user feedback. If you desire, it can be aligned just as regular text and some padding added to space it from the surrounding text, just like it were a span element.

As said in the comment i doubt less can do this.
Although you might want to use the meter HTML5 tag like so
<meter value="2" min="0" max="10">2 out of 10</meter><br>
<meter value="0.6">60%</meter>
Here is an example
http://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_meter
I think this is what you wanted to achieve from your script.

Related

CSS to put a character between two HTML tags only if there is something in both

I've got two values in my Model where either or both can contain a value. If both contain a value, I want to put a dash between them in the View. So, using span tags as containers for the properties, the output HTML will be
<span>First</span><span></span>
<span></span><span>Second</span>
<span>First</span>-<span>Second</span>
I can ViewModel this but I wanted to know if it was possible using just HTML/CSS. I've tried using the before and after CSS commands to insert the dash, but it doesn't do the job.
Any ideas if it's possible and if so, how?
CSS doesn't support inserting generated content before or after an element, so a pure solution to this isn't going to be straightforward.
If your spans need to be inline, or if you can't modify your HTML (e.g. the dash must appear between the two spans), you're better off handing this logic over to either JavaScript or the view model (or I guess both, if you're using a JavaScript MVVM framework).
If not, and you don't mind cheating a little and/or utterly trashing the semantics of your HTML, placing the dash in a third span following the first two allows you to show it using span:not(:empty) + span:not(:empty) + span and hide it otherwise.
Or, depending on how your layout works, you may be able to cheat in other ways. For example, if putting the dash in one of your spans is an option (e.g. because the spans don't have any special formatting), it's as easy as
span:not(:empty) + span:not(:empty)::before { content: '-'; }
Whichever it is, though, I suspect you'll invariably have an easier time just exposing a separate property in your view model.
So here it is a quick tricky way with just html & css complex selectors.
The base here is to include the dash - on the second element if it is not empty.
And if the first element is empty then push the second to offset and hide the dash.
div {
overflow: hidden;
line-height: 2em;
}
div span:first-child:empty {
margin-left: -10px;
}
div span:last-child:not(:empty):before {
content: "-";
width: 10px;
text-align: center;
display: inline-block;
}
<div><span>First</span><span></span></div>
<div><span></span><span>Second</span></div>
<div><span>First</span><span>Second</span></div>
Using the + adjacent selector will be like:
div {
overflow: hidden;
line-height: 2em;
}
div span:first-child:not(:empty) + span:not(:empty):before {
content: "-";
width: 10px;
text-align: center;
display: inline-block;
}
<div><span>First</span><span></span></div>
<div><span></span><span>Second</span></div>
<div><span>First</span><span>Second</span></div>
Yes, it's possible, though I think there are probably better ways to do it, like at the time the data is added.
Here's my solution.
span:nth-child(odd):not(:empty)+span:nth-child(even):not(:empty)::before {
content: '-'
}
<span>First</span><span></span>
<span></span><span>Second</span>
<span>First</span><span>Second</span>
<br><br>
<span>First</span><span></span><br>
<span></span><span>Second</span><br>
<span>First</span><span>Second</span>
What I'm saying is whenever there is an odd position span that is not empty it will update the next even position span if it's not empty with a hyphen.
I hope you find this helpful 🙂
In CSS, ::after creates a pseudo-element that is the last child of the selected element. It is often used to add cosmetic content to an element with the content property. It is inline by default.
<!DOCTYPE html>
<html>
<head>
<style>
.hypen-text::after {
content: "-";
}
}
</style>
</head>
<body>
<span>first</span>
<span>second</span>
<span class="hypen-text">first</span><span>second</span>
</body>
</html>
if you have still doubt refer this link https://developer.mozilla.org/en-US/docs/Web/CSS/::after
I used #Boltclock's answer
span:not(:empty) + span:not(:empty)::before { content: '-'; }
which made it surprisingly easy (when you know how) and just added classes to the spans so I can make sure it only happens where I need it to and so I can follow what's happening a bit more easily when I come back to this in a week's time :) The HTML I used is
<span class="spnAddADash">
<span class="spnValueOne">First</span>
<span class="spnValueTwo">Second</span>
</span>
And the corresponding style is
.spnAddADash .spnValueOne:not(:empty) + .spnValueTwo:not(:empty)::before {
content: '- ';
}
which both together render
First
Second
First - Second

How to modify content with CSS?

WARNING:
I do not recommend anyone to do this. It's an ugly hack.
I've got the code (minimized for the example)
<div id="somecontent">
<a name="content"></a>
Content to be changed
</div>
JSFiddle: https://jsfiddle.net/zalun/o733uyvs/
I'd like to change the "Content to be changed" with CSS.
Is this even possible (all ugly hacks included)?
It's easy when HTML is modified (<span> added) as in second block in mentioned fiddle.
Note: What you are trying to do is not recommended. I am providing you
a solution because I think you do not have access to source HTML or
your content is generated dynamically. I would still suggest you too
either change the source file or modify the DOM node using JavaScript.
I would say No and Yes.
Why No?
That's a text node. You cannot manipulate DOM nodes using CSS. You need to use JavaScript for that.
Why Yes? (Using ugly hacks), How?
Using content property as you are already using, but you cannot change the DOM, so you can make it super ugly like
Demo
#somecontent {
color: transparent;
position: relative;
}
#somecontent a:before {
content: "My new content";
color: #000;
position: absolute;
}
JavaScript Solution :
Demo
// You'll see text flicker
var t = document.getElementById('somecontent');
t.textContent = 'New Text';

Adding a space to a phone number with just CSS

I have a page which generates a phone number in HTML, like this:
<div class="phone">01987123456</div>
What I want is to simply put a space inside the number, like so:
01987 123456
The generated number and HTML will always be the same, but I only have access to client side code (HTML / CSS / Javascript / etc).
I want to find a way of achieving all of this without using Javascript if possible, so Ideally I am looking for an answer in CSS or HTML.
I'm pretty sure this could be done fairly easily in Javascript, but the client wants to make sure the phone number is formatted correctly even if Javascript is disabled (don't ask).
I want the most effective and efficient way of changing the number to what I want. If someone can figure out how to add brackets to the number (like this: (01987) 123456) as well as the space using just CSS/HTML you will immediately get marked as correct as well as my eternal gratitude.
EDIT:
I get that CSS is for design, Ive been a web developer for 15+ years. I could really do with a CSS hack to produce what I want, and explaining to the client the basics of web design is unfortunately not an option (they think they know better and I am in no position to dictate anything to them). I'm in a bit of a nightmare situation, and I need your help!
I know that content can be added to a page with CSS using content. I am aware of the ::first-letter method that #gillesc mentions in the comments. I was hoping something like this might help me.
The client uses modern browsers so a CSS3 solution would be fine.
And no, I cant change the outputted HTML.
I was interested to see if this could be done with CSS, even if it shouldn't be done! The following is quite hacky, ideally the phone number would be formatted server side or, if that isn't an option, with JavaScript.
A few caveats:
This requires an attribute to be added to .phone for the pseudo element to use. This may or may not be a deal breaker given that you seem to have limited access to the HTML
If the phone number is not in a suitable format (e.g. something like 01 987123456) it will not display correctly
A nasty little hack is used for IE as it doesn't calculate the width of the pseudo element correctly using ch for some reason. Credit to SW4 for this: https://stackoverflow.com/a/20541859
A solid background colour is required
The general idea behind this is as follows:
.phone
text-indent: 1ch; on .phone moves the whole text to the left by one character
.phone is set to position: relative; to allow the pseudo element to be positioned relatively to it
white-space: nowrap; ensures that this doesn't wrap onto a new line if there is a break in the number
.phone:before
background-color: white; masks the digits in .phone
border-right: 1ch solid white; hides the sixth digit in .phone, in effect this is the space
content: attr(data-phone); uses the data-phone attribute on .phone to populate the pseudo element with the same number
left: 0;, position: absolute; and top: 0; are used to position the pseudo element
overflow: hidden; hides any characters over the 5 character limit
text-indent: 0; resets text-indent: 1ch; set on .phone
width: 5ch; ensures that the pseudo element is only 5 characters long
The weird media query is the hack to target IE
Tested and working in FF 38.0.5, Chrome 43.0.2357.124 m and IE 11. Browsers not supporting the ch unit (such as Opera 12.17 and Windows Safari 5.1.7) seem to show the phone number in its natural state.
.phone {
position: relative;
text-indent: 1ch;
white-space: nowrap;
}
.phone:before {
background-color: white;
border-right: 1ch solid white;
content: attr(data-phone);
display: block;
left: 0;
overflow: hidden;
position: absolute;
text-indent: 0;
top: 0;
width: 5ch;
}
#media screen and (min-width:0\0) and (min-resolution: +72dpi) {
.phone:before {
width: 5.8ch;
}
}
<div class="phone" data-phone="01987123456">01987123456</div>
JS Fiddle: https://jsfiddle.net/scarjnb1/
It's not possible using CSS, just JavaScript. Then it'd be:
<div id="phone">01987123456</div>
<script>
var el = document.getElementById('phone');
phone.innerText = phone.innerText.replace(/^(\d{5})/, '($1) ');
</script>

Hide all, show a class with css

Context: making printable invoices to generate in a browser.
It's common in making printable webpages to use an #media print rule to change the way the content looks for a printed page. Ideally, because I'm printing only a small part of the page, I'd like to hide everything and then display the contents of a particular element.
Structure is something like this:
<body>
<div id="topMenu">...lots of elements...</div>
<div id="sideMenu">...lots more...</div>
<div class="tools">...some tools...</div>
<div class="printing">...some elements I want to print...</div>
<div class="tools">...more stuff I don't want to print...</div>
</body>
Stuff I've tried:
Ideally, I'd like to do something like
body * {
display: none;
}
.printing, .printing * { /* Both parts are needed to make it display */
display: block !important;
}
But this won't work because some elements need to be inline and some need to be block. I've played with some different values for display from MDN and can't find one that easily resets the value to its original. display: initial seems to be treated like inline.
The suggestion in CSS: "display: auto;"? seems to only work for JS.
Of course, it is possible to explicity "hide" the stuff I don't want printed rather than display the stuff I do want, but it seems to me that it should be possible to go the other way.
In this question How to only show certain parts with CSS for Print? suggests body *:not(.printable *) {display:none;} but notes (as backed up on the w3 negation page ) that this is not yet supported.
I note that the w3 draft and the display-outside page seem to recommend using an unknown (to webkit) box-suppress property to preserve the display value while not displaying the element.
My questions:
What is the best way to hide everything and target certain elements for display when they don't all share a common display property?
What exactly does box-suppress do?
Since you specifically tagged this CSS3, try using CSS3!
body>:not(.printing) {
display: none;
}
This should work for the example you gave. I hope it works for your real-world application!
To answer your auxiliary question, as of October 2014, box-suppress is a possible future replacement for display:none that will hopefully make it easier to both hide and remove elements from the flow without worrying about changing its display type (as opposed to visibility still keeps it in the flow, and position:absolute which still keeps it visible). I don't think it's currently supported so I'd stay away from it for now. If you want to know more, see http://w3.org/TR/css-display
You cannot use display for this purpose. See Display HTML child element when parent element is display:none
However, you can use visibility, as long as you use absolute positioning for the hidden content:
body, body * {
visibility: hidden;
position: absolute;
}
.printing, .printing * {
visibility: visible;
position: relative;
}
If you don't use any absolute or fixed elements, you can use an alternative way of hiding elements.
Instead of using display: none to hide your elements, try using:
body * {
position:absolute;
top: -999999px;
left: -999999px;
}
To set it back use:
.printing, .printing * {
position: initial;
/* OR */
position: static;
}

Are we supposed to be able to trust empty DIVs to show in HTML5?

Having seen advice seemingly change over the years regarding use of empty DIVs (ie. <DIV CLASS="somediv"></DIV>) I'm confused as to the current thinking over whether or not to use when a DIV will have no inner HTML.
I can find no definitive confirmation over whether we can rely on all modern browsers to display background color and image correctly at the specified width & height when there is no inner HTML, so I'm thinking maybe we can't rely on it - yet it's such a seemingly basic area.
I have even seen suggestions that empty DIVs should never be used - but do specs really state it is 'wrong' to have empty DIVs, or is it just unreliable? (I've tried finding reference to them, but maybe I'm using the wrong terms).
To illustrate, here are 5 areas where I would normally use an empty DIV, in the absence of any recommended alternative:
as a placeholder for content which will subsequently be fetched by XHR calls
as a way to manually create space in a layout
where an image is defined in CSS (as a background image, but will effectively be foreground)
where the text will come from the CSS using .somediv:after{content:SOMETEXT}
where CSS is used to display graph bars etc using solid background color
Maybe there are different answers for each of these, which might explain the complexity over this issue.
I have, of course, tried discovering already, but for example the SO question Is necessary to show an empty <div>? suggests to me there is a huge amount of "IMHO", "probably", "seems to work" in this area. I would expect that by now that some official consensus has been reached on best practice.
So.. should I use and if so should I set font-size to the same as the smaller of DIV width/height to ensure that space is filled in all browsers? Are there any other CSS tricks to ensure this will work in all browsers?
The browser is not going to discard or forget your container just because it does not have any contents (yet).
If you want the container to have a specific placeholder shape, then you might give it min-height, min-width, height and width and make sure it's display: block;.
If you are still unsure, you can fill it with a spacer.gif/png without padding and margin.
http://jsfiddle.net/APxNF/1/
Short answer. Yes, browsers will render the div even if there is no content.
Long answer, That might now always be the case. I have worked in the web for 8 years now and never had to use these, but here they are anyway.
jsFiddle demo
HTML
<div class="empty1"></div>
<div class="empty2"></div>
<div class="empty3"></div>
CSS
.empty1 {
background: #FBB829;
height: 100px;
width: 100px;
}
.empty2:before {
content: "\00a0";
}
.empty2 {
background: #FF0066;
height: 100px;
width: 100px;
}
.empty3 {
background: #F02311;
min-height: 1px;
height: 100px;
width: 100px;
}
Sources:
Experience
Empty div with 2px width and background color doesnt show with height as 100%
http://csscreator.com/node/36023