Get first/last part of attribute via CSS attr() - html

Is it possible to get only the first part of an attribute using attr() in CSS? By this I mean, targeting the part of an attribute before a certain character (a space, mainly). For example, from the attribute hello="foo bar" I would like to extract either foo or bar, just by using CSS.
Sincerely, I'd expect the answer to be 'no', but I'm not really sure.

The generic answer is no but in some particular case we can find some tricks. Since you have a space as a delimiter we can rely on word-spacing and/or text-indent and some overflow in order to hide a part of the word then adjust the width.
Here is an example:
.first:before {
content: attr(data-hello);
word-spacing: 50px;
display: inline-block;
vertical-align: top;
max-width: 40px;
overflow: hidden;
white-space: nowrap;
}
.first:after {
content: attr(data-hello);
text-indent: -60px;
word-spacing:50px;
display: inline-block;
vertical-align: top;
max-width: 40px;
overflow: hidden;
white-space: nowrap;
}
<span class="first" data-hello="foo bar">
some text
</span>

Related

Slash in right to left latin text

I wanted to ellipse a latin text from lefthand side (It represents a path). Something like the following figure:
To making this I found the following css:
.ellipsis-left {
/* Standard CSS ellipsis */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex-grow: 1;
/* Beginning of string */
direction: rtl;
text-align: left;
color: blue;
}
.red {
color: red;
}
and I use it like this:
<div class="ellipsis-left">
/Pollution/<span style="red">Air Pollution/</span>
</div>
But the problem is that slashes which separate parts of the path are not placed in the right position. In the following figure, the red slash must be shown at the end of the path. Is there any solution to solve this problem?
I want to reach something like this:
At the moment, as a solution I color the first slash with red as it places at the end of the string! Something like this:
<div class="ellipsis-left">
<span style="red">/</span>Pollution/<span style="red">Air Pollution</span>/
</div>
But this is not a good solution!
I had a similar problem and worked around it by stripping of the leading slashes in my paths. Slashes in the middle don't seem to be an issue.
Bit of a tricky situation you got there. The / aren’t normal letters, but rather fall under punctuation - and so they get treated differently by the LTR algorithm.
Tried different things - making the spans rtl again did not work, inserting the / as pseudo elements and trying to format them differently didn’t get me anywhere, and making the spans inline-block breaks the whole LTR thing of the parent …
Only thing I could come up with that seems to work, is to position those / absolutely. So they need wrapping into an element of their own, and the first path segment also needs to be wrapped in a span. You might wand to fiddle with the padding a bit, to get the spacing exactly right.
.ellipsis-left {
/* Standard CSS ellipsis */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex-grow: 1;
/* Beginning of string */
direction: rtl;
text-align: left;
color: blue;
width:9em;
}
.ellipsis-left > span {
direction: ltr;
position: relative;
padding-right: .375em;
}
.ellipsis-left > span span {
position:absolute;
right: 0;
}
.red {
color: red;
}
<div class="ellipsis-left">
<span>Pollution<span>/</span></span><span class="red">Air Pollution<span>/</span></span>
</div>
But wait, you want a leading slash in front of the whole thing as well … and that’s where it breaks again. Trying to add that into the “Pollution” span as well, I had it end up at the very end again, and putting it into its own “empty” path segment (<span><span>/</span></span>) did not work either. It does work, if that element contains an actual letter - but then I am having trouble “hiding” that again (plus, semantically really ugly) - wrapping the latter into another additional element, so that I could apply inline-block and a zero width to hide it, broke the whole thing again.
Using visibility to hide that extra letter worked, and a bit of negative margin helps hide the offset that leaves:
.ellipsis-left {
/* Standard CSS ellipsis */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex-grow: 1;
/* Beginning of string */
direction: rtl;
text-align: left;
color: blue;
width:9em;
}
.ellipsis-left:nth-child(2) {
width: auto;
}
.ellipsis-left > span {
direction: ltr;
position: relative;
padding-right: .375em;
}
.ellipsis-left > span span {
position:absolute;
right: 0;
}
.ellipsis-left > span:first-child {
visibility:hidden;
margin-left: -.5em;
}
.ellipsis-left > span:first-child span {
visibility:visible;
}
.red {
color: red;
}
<div class="ellipsis-left">
<span>X<span>/</span></span><span>Pollution<span>/</span></span><span class="red">Air Pollution<span>/</span></span>
</div>
<div class="ellipsis-left">
<span>X<span>/</span></span><span>Pollution<span>/</span></span><span class="red">Air Pollution<span>/</span></span>
</div>
As I said, semantically rather ugly … but the best I managed to come up with so far.
Maybe someone can think of an alternative approach that works, something with flexbox and its order property or something.

Reversed characters when providing another string to text-overflow: ellipsis;

I'm trying to create a text-overflow: ellipsis; from the beginning, but in some specific context, it reverses the characters.
This is a CodePen to illustrate the problem: https://codepen.io/DWboutin/pen/yLaoxog
HTML:
<div class="ellipsis">Path to you prefered files that you love so much forever and ever fuck yeah</div>
<div class="ellipsis">1":"#323130",messageLink:t?"#6CB8F6":"#005A9E",messageLinkHovered:t?"#82C7FF":"#004578",infoIcon:t?"#</div>
CSS:
div {
margin: 10px 0;
border: 1px solid black;
}
.ellipsis {
width: 400px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
direction: rtl;
}
I tried all word-break properties, wrapping the string into another span to force it to be ltr but it don't work.
Thank you for your help
unicode-bidi might help you with an extra wrapper to handle text direction:
https://developer.mozilla.org/en-US/docs/Web/CSS/unicode-bidi
The unicode-bidi CSS property, together with the direction property, determines how bidirectional text in a document is handled. For example, if a block of content contains both left-to-right and right-to-left text, the user-agent uses a complex Unicode algorithm to decide how to display the text. The unicode-bidi property overrides this algorithm and allows the developer to control the text embedding.
div {
margin: 10px 0;
border: 1px solid black;
width:max-content;
}
.ellipsis {
width: 400px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
direction: rtl;
}
.ellipsis span {
direction: ltr;
unicode-bidi: bidi-override;
}
<div class="ellipsis">Path to you prefered files that you love so much forever and ever fuck yeah</div>
<div class="ellipsis"><span>1":"#323130",messageLink:t?"#6CB8F6":"#005A9E",messageLinkHovered:t?"#82C7FF":"#004578",infoIcon:t?"#</span></div>
original text :
<div>Path to you prefered files that you love so much forever and ever fuck yeah</div>
<div><span>1":"#323130",messageLink:t?"#6CB8F6":"#005A9E",messageLinkHovered:t?"#82C7FF":"#004578",infoIcon:t?"#</span></div>
Note, that extra wrapper needs to remain an inline element (display:inline) , an inline-box will not be part of the ellipsis rule but will overflow to the left, a block element will overflow on the right.

Disable selectability for a space in <code> tag

Building on Disable selectability for a space I now have an even more special problem. Basically, I have the following code:
.meta {
user-select: none;
}
.bash {
display: inline-block;
}
.meta:after {
content: '\00a0';
}
<pre><code><span class="meta">$</span><span class="bash"> ls</span></code></pre>
Now, I want the user to be able to select the ls, but not the $ (including the space). While this already works for the $ character, it does not work for the space after it. How can this be solved?
And, due to the <pre> tag there are now two spaces: While the one inserted by CSS can not be selected, the other one still can. One way to solve this is to add a text-indent: -7px and a overflow-x: hidden to the .bash class, but this breaks the layout (for whatever reason).
So, how can this be fixed without touching the HTML? (Please note that I have no influence on the HTML code, only on the CSS.)
pre tag preserves spaces and line breaks, you need to set .bash's white-space to initial, but IE does not take initial value so it's better to use both white-space: normal; and white-space: initial;
.meta {
user-select: none;
}
.bash {
display: inline-block;
white-space: normal;
white-space: initial;
}
.meta:after {
content: '\00a0';
}
<pre><code><span class="meta">$</span><span class="bash"> ls</span></code></pre>

How to not display css padding when span element is empty

I've been trying to solve the following problem.
If you run this code you will notice blue and red elements.
How can I hide the 'red element' when there is no text to display (span is empty). And I would like to do the same thing with 'blue element' when there is no text inside it shouldn't be visible.
The reason why is displayed is padding, but I would like to have padding because it looks nice.
I am sure you guys are best of the best and find solution.
Regards!
.myClassDer {
font-size: 34px;
color:white;
background: blue;
color: white;
border-radius: 25px;
padding: 7px;
width: auto;
height: auto;
}
.myClassDie {
font-size: 34px;
color:black;
background: red;
color: white;
border-radius: 25px;
padding: 7px;
width: auto;
height: auto;
}
<span class="myClassDer">here</span>
<span class="myClassDie"></span>
If you don't require support for IE8, you can use pseudo-state :empty (here for more examples ) to reset padding for all instances of .myClassDie without content, using the following code.
.myClassDie:empty
{
padding:0;
}
Updating your working example, it becomes:
.myClassDer
{
font-size: 34px;
color:white;
background: blue;
color: white;
border-radius: 25px;
padding: 7px;
width: auto;
height: auto;
}
.myClassDie
{
font-size: 34px;
color:black;
background: red;
color: white;
border-radius: 25px;
padding: 7px;
width: auto;
height: auto;
}
.myClassDie:empty
{
padding:0;
}
<span class="myClassDer">here</span>
<span class="myClassDie"></span>
<span class="myClassDie">ClassDie but with content</span>
In which I inserted two <span class="myClassDie"> to show you the behaviour with and without content.
Due to effective invisibility of "empty" case, if you want a more compact solution, you can collapse the two separate rules into only one, simply setting:
.myClassDie:not(:empty)
{
font-size: 34px;
color:black;
background: red;
color: white;
border-radius: 25px;
padding: 7px;
width: auto;
height: auto;
}
In this case, only if .myClassDie is not empty, you'll apply all properties.
This is equivalent for this specific case, but if you want to see this DIV also if empty, limiting only to reset padding (for example because it has fixed size or borders), you must use first solution, not the more compact one.
Little precisation about :empty pseudo-class
Previous examples run correctly only if empty elements are effectively empty, this means that this code <span class="myClassDie"></span> is correctly targeted, but this one (that contains a whitespace) <span class="myClassDie"> </span> isn't.
In general, this could be an issue because often code is dynamically generated or otherwise contains white spaces due to code indentation.
In the past, Mozilla introduced its proprietary pseudo-class :-moz-only-whitespace, but no other browser currently supports this yet.
W3 also tried to solve this kind of problems, initially with analogue :blank pseudo-class (again with no browser support) in "Selectors Level 3", but this did not have expected success.
So, since beginning of 2018, W3 modified its definition to represent empty user input, rather than empty elements and contemporarily modified :empty definition to consider also white-spaces, but currently this last feature is not implemented too in different browsers.
Empty pseudo class only checks for empty text
.myClassDie:empty{
padding:0;
}
But for whitespaces use blank pseudo class
.myClassDie:blank{
padding:0;
}
There is a css pseudoclass empty which you could use here:
.myClassDie:empty {
display: none;
}
Your updated JSFiddle
You can do the trick with the CSS3 pesudo-class :empty
span:empty{
padding:0;
}
Note: using above selector you will not have to worry about which span
has value and which one has not. it will reset padding for those span
which are blank (empty).
I guess you could use above piece of code to hide the empty span's padding.
span:empty {
padding: 0;
}
you can you :empty also read the below like.
https://developer.mozilla.org/en-US/docs/Web/CSS/pseudo-classes
.myClassDie:empty {padding:0;}

Handle text as elements, how to hide with CSS?

I have a div with content like this:
<div class="myDiv">
Here's some text that vary in length <span class="separator">/</span> Some other text <_other elements etc>
</div>
What I want is, only using CSS, to display the first text and hide the rest.
I have tried .myDiv *:not(:first-child) { display: none; } which hides all elements, except the first separator. All texts are still visible.
Is this even possible, only using CSS?
Edit: the text is in variable lenght, but this variation is restricted between 14 and 21 chars. It will never be line breaked. (Added this info for solutions like set the div to a width and visibility:hidden or solutions like that which is fully acceptable)
This is how I would do it:
<div class="myDiv"><span>Here's some text that vary in length</span> <span class="separator">/<span><span> Some other text </span><span><_other elements etc></span>
</div>
.myDiv > span:not(:first-child) {
display:none;
}
Here is the JSFiddle demo
Separate your text using span properly and then apply the css to hide the spans if its not the first-child
It is not possible to directly select text nodes using CSS so the logical way of achieving this would be to wrap the text in an element and hide that. Unfortunately, this is not an option in this instance as the HTML markup cannot be modified and JavaScript cannot be used.
Luckily, we can rely on two things:
The text will always be on one line
The .separator element will exist
We can therefore use a combination of overflow on .myDiv and a pseudo element in .separator to forcibly hide the unwanted text:
Add height: 1em; and line-height: 1em; to .myDiv to force it only to show one line of text
Add overflow: hidden; to .mDiv to ensure that the overflown content is hidden
Create an :after pseudo element in .separator and set it to display: block; to ensure that it is forced onto a new line. This will ensure that the separator itself (/) is still shown
.myDiv {
height: 1em;
line-height: 1em;
overflow: hidden;
}
.separator:after {
content:"";
display: block;
}
<div class="myDiv">Here's some text that vary in length <span class="separator">/</span> Some other text
<_other elements etc>
</div>
If the separator is not required the CSS can be simplified. The pseudo element can be removed and .separator itself can be set to display: block; to force it onto a new line.
.myDiv {
height: 1em;
line-height: 1em;
overflow: hidden;
}
.separator {
display: block;
}
<div class="myDiv">Here's some text that vary in length <span class="separator">/</span> Some other text
<_other elements etc>
</div>
Edited You can Use this also
.myDiv{
max-width: 28.5ch;
overflow: hidden;
white-space: nowrap;
}
OR
<style>
.myDiv *:first-child
{
display:none;
}
</style>
<div class="myDiv">Here's some text that vary in length <span class="separator"> Some other text <_other elements etc></span>