Conditional Css for text length - css

I have a div with certain text contained inside it. When the Text is of a certain length (Say 15 characters or more), the width of the div should change. Is there any way to achieve this purely via CSS?

You can use JS for it...
if textContent.length > 15 the add class to label and style in css(width and ect)
var lbl=document.querySelector(".lbl");
if(lbl.textContent.length > 15){
lbl.classList.add('bigger');
}
.bigger{
color:red
}
<label class="lbl">avvvvvvvvvvvvvvvvvvvvvvb<label>

with pure css, you can only fit content with div:
div { display:inline-block;}
else if you want more complicated conditions, You can't do it with pure css.you must help of javascript like this:
var con = document.getElementsByTagName("div");
if((con[0].innerHTML).length >= 15) { con[0].style.width = '300px'; }
var con = document.getElementsByTagName("div");
if((con[0].innerHTML).length >= 15)
con[0].style.width = '300px';
div {
width: 50px;
border: 1px solid red;
}
<div>This is more 15 characters</div>

Related

CSS on :focus within child of contenteditable

I am trying to detect focus on a child element of a contenteditable element, for the purposes of pure CSS styling. (I know I could detect this with JS, add an extra class and do it that way, but that is so long-winded.)
Basically, I have something along the lines of:
<div contenteditable="true">
Some text <span class="edit">that</span> goes here.
</div>
I tried CSS along the lines of:
.edit:focus {
color: #FF0000;
}
I want that span to change colour when the caret enters it, but apparently the focus is only applied to the div set to contenteditable, not to any child thereof. I have tried applying a second contenteditable to the span, but besides being a horribly sloppy approach, it doesn't work anyway.
Is there a solution to this?
Because of the limitation that elements within a contenteditable element can't generally receive focus, I suggest faking it by adding a class to your <span> element when the selection is contained within it, which you can do by monitoring the selection for changes (you'll have to use mouse and keyboard events and polling for thoroughness in Firefox until the selectionchange event is implemented in that browser).
var selectionContainer = null;
function updateSelectionContainer() {
var newSelectionContainer = null;
var sel;
if (window.getSelection && (sel = window.getSelection()).rangeCount) {
newSelectionContainer = sel.getRangeAt(0).commonAncestorContainer;
// Ensure we have an element rather than a text node
if (newSelectionContainer.nodeType != 1) {
newSelectionContainer = newSelectionContainer.parentNode;
}
}
if (newSelectionContainer != selectionContainer) {
if (selectionContainer) {
selectionContainer.className = selectionContainer.className.replace(/ ?containsSelection/, "");
}
if (newSelectionContainer) {
newSelectionContainer.className +=
(newSelectionContainer.className ? " containsSelection" : "containsSelection");
}
selectionContainer = newSelectionContainer;
}
}
if ("onselectionchange" in document) {
document.onselectionchange = updateSelectionContainer;
} else {
var el = document.getElementById("editor");
el.onmousedown = el.onmouseup = el.onkeydown = el.onkeyup = el.oninput = updateSelectionContainer;
window.setInterval(updateSelectionContainer, 100);
}
div {
font-size: 200%;
}
.edit.containsSelection {
color: red;
font-weight: bold;
}
<div contenteditable="true" id="editor">
Some text <span class="edit">that</span> goes here.
</div>
My understanding is that the type of elements that can receive focus (automatically) is limited.
See SO Question
One option is to add tabindex to the span.
body {
font-size: 3rem;
}
div[contenteditable=true] .edit:focus {
color: #FF0000;
}
<div contenteditable="true">Some text <span class="edit" tabindex="0">that</span> goes here.</div>
:focus > .edit { color: #cc0000; }
<div contenteditable="true">Some text <span class="edit">that</span> goes here.</div>
<div contenteditable="true">Some text that goes here.</div>
Just add this instead of :focus. Fiddle.
.edit {
color: #f00;
}

Using HTML data-attribute to set CSS background-image url

I plan on building a custom photo gallery for a friend and I know exactly how I am going to be producing the HTML, however I am running into a small issue with the CSS.(I would prefer to not have the page styling rely on jQuery if possible)
My question regards:
Data-Attribute in HTML
Background-image in CSS
I am using this format for my html thumbnails:
<div class="thumb" data-image-src="images/img.jpg"></div>
and I assume the CSS should look something like this:
.thumb {
width:150px;
height:150px;
background-position:center center;
overflow:hidden;
border:1px solid black;
background-image: attr(data-image-src);/*This is the question piece*/
}
My goal is to take the data-image-src from the div.thumb in my HTML file and use it for each div.thumb(s) background-image source in my CSS file.
Here is a Codepen Pen in order to get a dynamic example of what I am looking for:
http://codepen.io/thestevekelzer/pen/rEDJv
You will eventually be able to use
background-image: attr(data-image-src url);
but that is not implemented anywhere yet to my knowledge. In the above, url is an optional "type-or-unit" parameter to attr(). See https://drafts.csswg.org/css-values/#attr-notation.
If you wanted to keep it with just HTML and CSS you can use CSS Variables.
Keep in mind, css variables aren't supported in IE.
<div class="thumb" style="--background: url('images/img.jpg')"></div>
.thumb {
background-image: var(--background);
}
Codepen: https://codepen.io/bruce13/pen/bJdoZW
It is not best practise to mix up content with style, but a solution could be
<div class="thumb" style="background-image: url('images/img.jpg')"></div>
You will need a little JavaScript for that:
var list = document.getElementsByClassName('thumb');
for (var i = 0; i < list.length; i++) {
var src = list[i].getAttribute('data-image-src');
list[i].style.backgroundImage="url('" + src + "')";
}
Wrap that in <script> tags at the bottom just before the </body> tag or wrap in a function that you call once the page loaded.
How about using some Sass? Here's what I did to achieve something like this (although note that you have to create a Sass list for each of the data-attributes).
/*
Iterate over list and use "data-social" to put in the appropriate background-image.
*/
$social: "fb", "twitter", "youtube";
#each $i in $social {
[data-social="#{$i}"] {
background: url('#{$image-path}/icons/#{$i}.svg') no-repeat 0 0;
background-size: cover; // Only seems to work if placed below background property
}
}
Essentially, you list all of your data attribute values. Then use Sass #each to iterate through and select all the data-attributes in the HTML. Then, bring in the iterator variable and have it match up to a filename.
Anyway, as I said, you have to list all of the values, then make sure that your filenames incorporate the values in your list.
HTML
<div class="thumb" data-image-src="img/image.png">
jQuery
$( ".thumb" ).each(function() {
var attr = $(this).attr('data-image-src');
if (typeof attr !== typeof undefined && attr !== false) {
$(this).css('background', 'url('+attr+')');
}
});
Demo on JSFiddle
You could do this also with JavaScript.
For those who want a dumb down answer like me
Something like how to steps as 1, 2, 3
Here it is what I did
First create the HTML markup
<div class="thumb" data-image-src="images/img.jpg"></div>
Then before your ending body tag, add this script
I included the ending body on the code below as an example
So becareful when you copy
<script>
var list = document.getElementsByClassName('thumb');
for (var i = 0; i < list.length; i++) {
var src = list[i].getAttribute('data-image-src');
list[i].style.backgroundImage="url('" + src + "')";
}
</script>
</body>
Here is simple example using jQuery we can put the images in background
$('*[data-background-image]').each(function() {
$(this).css({
'background-image': 'url(' + $(this).data('background-image') + ')'
});
});
div{
height:200px;
width:100% ;
background-size: cover;
background-position: center center;
background-repeat: no-repeat;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div data-background-image="https://via.placeholder.com/500"> </div>
HTML CODE
<div id="borderLoader" data-height="230px" data-color="lightgrey" data-
width="230px" data-image="https://fiverr- res.cloudinary.com/t_profile_thumb,q_auto,f_auto/attachments/profile/photo/a54f24b2ab6f377ea269863cbf556c12-619447411516923848661/913d6cc9-3d3c-4884-ac6e-4c2d58ee4d6a.jpg">
</div>
JS CODE
var dataValue, dataSet,key;
dataValue = document.getElementById('borderLoader');
//data set contains all the dataset that you are to style the shape;
dataSet ={
"height":dataValue.dataset.height,
"width":dataValue.dataset.width,
"color":dataValue.dataset.color,
"imageBg":dataValue.dataset.image
};
dataValue.style.height = dataSet.height;
dataValue.style.width = dataSet.width;
dataValue.style.background = "#f3f3f3 url("+dataSet.imageBg+") no-repeat
center";

Select all by class except last

I have a series of div and I would like to select all p tags with enable class except the last inside each div in order to apply a specific style in css. The content are dynamically generated and may vary depending on the user.
In the example below, I would like to apply this style to the first two p inside the first div and none inside the other. I'm sure it's pretty easy but I don't find any solution to solve it.
<div>
<p class="enable"></p>
<p class="enable"></p>
<p class="enable"></p>
<p class="disable"></p>
</div>
<div>
<p class="enable"></p>
<p class="disable"></p>
<p class="disable"></p>
<p class="disable"></p>
</div>
Thanks for your help.
If the p elements are confined to four per div you can use the nth-child pseudo selector.
p.enable:nth-child(-n+2)
{
background: #0f0;
}
p.disable
{
background: #eee;
}
http://jsfiddle.net/Kyle_Sevenoaks/vw4wQ/
I have a Javascript solution for you:
var divs = document.getElementsByTagName("div"), paras, i, j;
for(i = 0; i < divs.length; i++) {
paras = divs[i].getElementsByTagName("p");
for(j = 0; j < paras.length-1; j++) {
if(paras[j+1].className === "disable")
break;
// apply your custom code here
paras[j].style.background = "#FF0000";
}
}
Check this solution in this jsFiddle

nesting css class for sprite image

I'm just bit confused on css Id/class nesting.
sample code below:
1) #sprit-img {
display:inline;
border:1px solid #FFF;
text-decoration:none;
display:block;
float:left;
width:50px;
height:50px;
background-image:url(ig-sprite.png);
background-repeat:no-repeat;
margin:5px;
}
2) #sprit-img a.brew{
background-position:2px 0px;}
3) #sprit-img a.scc{
background-position:-295px 2px;}
in page i used like
4) <div id="sprit-img><a class="brew"></a>...</div> `
now i want to use it like
5) <div class="sprit-img"><a class="brew"></a> <span class="scc"></span></div>`
Questions
is it necessary to give anchor or any element tag in code line 2 and 3?
what would be optimal way to get line 5(if Q1 is true, to have in css class i removed # and place . but not working in my page)? is this correct
--
6) .sprit-img{.....same code..}
.brew{...same position..}
.scc{..same postion...}
and use it like in line 5 or
this is correct
7) .sprit-img{.....same code..}
.sprit-img .brew{...same position..} `
Thanks.
edit: I tried some mix put background-image from sprit-img to brew and scc and found that if i put style as in 6 the html part should be like
<div class="anything"><span class="sprit-img brew"></span></div>
and if i put style like in 7 html part should be like
<div class="sprit-img"><span class="sprit-img brew"></span></div>
but could not make it like 5 any idea ...
Q.1: No.
Q.2:
You need a way to target both types of things inside your div at once in order to apply the same bg image, as well as a way to differentiate them. There are numerous solutions.
As long as you're sure that anything nested inside sprit-img should take the background, you could do this:
<div class="sprit-img">
<a class="brew"></a> <span class="scc"></span>
</div>
#sprit-img * { background-image:url(ig-sprite.png) };
#sprit-img .bew { background-position:2px 0px }
#sprit-img .scc { background-position:-295px 2px; }
(note: * is the universal selector)
...though that could get you in trouble if you need any markup inside of those elements (everything would take the background image, and it would be a funky jumble)
So, if you are sure all child elements (nested only 1 level down) should take the background, but nothing inside of those elements should, then you can use the child selector ( > ) like this:
<div class="sprit-img">
<a class="brew"><span> some text></span>some other text</a>
<span class="scc">more text <strong>something important</strong></span><
</div>
#sprit-img > * { background-image:url(ig-sprite.png) };
#sprit-img .bew { background-position:2px 0px }
#sprit-img .scc { background-position:-295px 2px; }
if you want to avoid the universal selector (rendering could be slow on older machines or with earlier browser versions), you could alternatively use (with line 5 markup):
#sprit-img > a, #sprit-img > span { background-image:url(ig-sprite.png) };
#sprit-img .bew { background-position:2px 0px }
#sprit-img .scc { background-position:-295px 2px; }
...which would then only apply to anchors and spans inside of an element with id="sprit-img"
Or you coulld avoid tag-names altogether (if you are super render-speed conscious) (with line 5 markup)
#sprit-img .bew, #sprit-img .scc { background-image:url(ig-sprite.png) };
#sprit-img .bew { background-position:2px 0px }
#sprit-img .scc { background-position:-295px 2px; }
...which illustrates why the answer to your first question is "no"
# is an ID selector, . is a class selector. So you could change to:
.sprit-img {...}
.sprit-img .brew {...}
.sprit-img .scc {...}
and
<div class="sprit-img"><a class="brew"></a> <span class="scc"></span></div>
However, the real problem is your trying to use non-cascading properties in .sprit-img on the child elements. The first selector should be changed to .sprit-img .brew, .sprit-img .scc

CSS text justify with letter spacing

Is there a way to automatically justify words using letter spacing, each in its row, to a defined width, using CSS?
For example, "Something like this" would look, well, something like this:
Is there a non-obtrusive way to apply such styling to my text? I believe pure CSS doesn't have this option (at least not with CSS versions before 3, CSS3 seems to have a text-justify property, but it's not well supported yet), so js solutions would be fine also.
Here's a script which can do it. It isn't pretty, but maybe you can hack it to meet your needs. (Updated to handle resizing)
function SplitText(node) {
var text = node.nodeValue.replace(/^\s*|\s(?=\s)|\s*$/g, "");
for (var i = 0; i < text.length; i++) {
var letter = document.createElement("span");
letter.style.display = "inline-block";
letter.style.position = "absolute";
letter.appendChild(document.createTextNode(text.charAt(i)));
node.parentNode.insertBefore(letter, node);
var positionRatio = i / (text.length - 1);
var textWidth = letter.clientWidth;
var indent = 100 * positionRatio;
var offset = -textWidth * positionRatio;
letter.style.left = indent + "%";
letter.style.marginLeft = offset + "px";
//console.log("Letter ", text[i], ", Index ", i, ", Width ", textWidth, ", Indent ", indent, ", Offset ", offset);
}
node.parentNode.removeChild(node);
}
function Justify() {
var TEXT_NODE = 3;
var elem = document.getElementById("character_justify");
elem = elem.firstChild;
while (elem) {
var nextElem = elem.nextSibling;
if (elem.nodeType == TEXT_NODE)
SplitText(elem);
elem = nextElem;
}
}
#character_justify {
position: relative;
width: 40%;
border: 1px solid red;
font-size: 32pt;
margin: 0;
padding: 0;
}
#character_justify * {
margin: 0;
padding: 0;
border: none;
}
<body onload="Justify()">
<p id="character_justify">
Something<br/> Like
<br/> This
</p>
</body>
The css only solution is text-justify: distribute https://www.w3.org/TR/css-text-3/#text-justify but the support is still very poor.
A small experiment using text-align-last: justify and adding spaces between letters.
div{
display:inline-block;
text-align: justify;
text-align-last: justify;
letter-spacing: -0.1em;
}
<div>
S o m e t h i n g<br>
l i k e<br>
t h i s
</div>
I know this is an old topic, but I faced this the other night. And found a suitable solution using tables.
Every letter shall be put into a <td> </td> I know it looks tedious, but if you wanna do this, it would be for a word or two, right? Or you always can use JS to fill it if is too much. However, this is only CSS and very versatile solution.
Using letter-spacing the letters get distributed properly. You should play around with it, depending on the width of the table.
#justify {
width: 300px;
letter-spacing: 0.5em;
}
<table id="justify">
<tbody>
<tr>
<td>J</td>
<td>U</td>
<td>S</td>
<td>T</td>
<td>I</td>
<td>F</td>
<td>Y</td>
</tr>
</tbody>
</table>
See the example here
Crossbrowser safe, virtually nothing shall differ. Is just CSS.
I used it in My website which is in english and spanish.
the subtitle under my name in spanish has an additional letter and it will step out the width. Using the tables explained above, it gets distributed to the same width automatically. Spacing it manually I'd had to define a whole condition for each language to go around that.
Here is an other aproach using a jQuery snippet I wrote for this question : Stretch text to fit width of div :
DEMO
HTML :
<div class="stretch">Something</div>
<div class="stretch">Like</div>
<div class="stretch">This</div>
jQuery :
$.fn.strech_text = function () {
var elmt = $(this),
cont_width = elmt.width(),
txt = elmt.html(),
one_line = $('<span class="stretch_it">' + txt + '</span>'),
nb_char = elmt.text().length,
spacing = cont_width / nb_char,
txt_width;
elmt.html(one_line);
txt_width = one_line.width();
if (txt_width < cont_width) {
var char_width = txt_width / nb_char,
ltr_spacing = spacing - char_width + (spacing - char_width) / nb_char;
one_line.css({
'letter-spacing': ltr_spacing
});
} else {
one_line.contents().unwrap();
elmt.addClass('justify');
}
};
$(document).ready(function () {
$('.stretch').each(function () {
$(this).strech_text();
});
});
Needed this too, so I've bundled the suggested technique in a simple to use jquery-plugin you can find here: https://github.com/marc-portier/jquery-letterjustify#readme.
It uses the same procedure at its core, and adds some options to tweak.
Comments welcome.
Found another way to achieve this with pure CSS, alas you need to spell out your words.
In my situation, this was the only solution that worked (some letters had classes), plus it also produced the straightest right-alignment among answers here, without using hacks.
.box {
width: min-content;
border: solid red;
}
.word {
display: flex;
justify-content: space-between;
}
<div class="box">
<div class="word">
<span>S</span>
<span>o</span>
<span>m</span>
<span>e</span>
<span>t</span>
<span>h</span>
<span>i</span>
<span>n</span>
<span>g</span>
<span> </span>
<span>w</span>
<span>i</span>
<span>c</span>
<span>k</span>
<span>e</span>
<span>d</span>
</div>
<div class="word">
<span>t</span>
<span>h</span>
<span>i</span>
<span>s</span>
<span> </span>
<span>w</span>
<span>a</span>
<span>y</span>
</div>
<div class="word">
<span>c</span>
<span>o</span>
<span>m</span>
<span>e</span>
<span>s</span>
</div>
</div>
Again, I know this is REALLY old, but why not just put a space between each letter and then text-align:justify? Then each letter would be regarded as a 'word' and justified accordingly
An alternate way to handle this might be to use the "vw" sizing unit. This unit type can be used in font size properties and represents a percent of the window's width.
Disclaimer: It is not exactly what you are looking for, but requires no scripting. It does adjust the text size, but will also scale to the width of your page.
For example,
.heading {
font-size: 4vw;
}
will make the width of one character in the current font 4% of the window width.
You could then use media queries if you wish to lock the font size to a minimum size based on the window's width.
#media only screen and (max-width: 768px) {
font-size: 2rem;
}
Use the browser inspector to play with the font-size property and tweak the value to what makes sense for your application.
The "vw" unit works in IE9+, iOS 8.3+ and Android 4.4+ and all other mainstream browsers. I wouldn't worry about the mobile support too much, as you can use media queries to put the right sizing for these devices as described above.
http://caniuse.com/#feat=viewport-units
https://css-tricks.com/viewport-sized-typography/
Viewport units are a powerful way to scale many different aspects of your site with little code.
I just made a JQuery script from table's Tony B approach.
Here is the JSFiddle https://jsfiddle.net/7tvuzkg3/7/
This script creates a table with each char in a row. This works with full sentence.
I'm not sure this is fully optimized.
justifyLetterSpacing("sentence");
function justifyLetterSpacing(divId) {
// target element
domWrapper = $('#' + divId).clone().html('');
// construct <td>
$('#' + divId).contents().each(function(index){
// store div id to td child elements class
var tdClass = divId ;
// split text
$textArray = $(this).text().split('');
// insert each letters in a <td>
for (var i = 0; i < $textArray.length; i++) {
// if it's a 'space', replace him by an 'html space'
if( $textArray[i] == " " ) {
$('<td>')
.addClass(tdClass)
.html(" ")
.appendTo(domWrapper);
}// if it's a char, add it
else{
$('<td>')
.addClass(tdClass)
.text($textArray[i])
.appendTo(domWrapper);
}
}
});
// create table
table =
$( "<table id='"+divId+"'/>" ).append(
$( "<tbody>" ).append(
$( "<tr>" ).append(
( domWrapper ).children('td')
)
)
);
// replace original div
$('#' + divId).replaceWith( table );
}
#sentence {
width : 100%;
background-color : #000;
color : #fff;
padding : 1rem;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="sentence">LOREM IPSUM DOLOR</div>
I usually try to write my answer on time. and this is exactly the same time (after 10 years) =)
myText.innerHTML = myText.textContent
.split(/\s+/g)
.map((line) => line.trim().split("").join(" "))
.join("<br>");
#myText {
display: inline-block;
text-align: justify;
text-align-last: justify;
letter-spacing: -0.125em;
font-family: sans-serif;
}
<div id="myText">Something like this</div>

Resources