Display second <span> element in front of first - css

I'm trying to get a second sibling element displaying in front of the first - with some severe restrictions:
I cannot alter the HTML or use javascript or jQuery.
I can only use CSS.
I can't change how classes are assigned (again, I don't have access to change any code apart from the one bespoke CSS file).
The left-hand menu features a number of the above HTML structures, building a clickable menu for the sections on the page. When a page section is completed, the 'completed-section' class is added to the first span (as shown above). This is what is causing me problems:
The CSS styling of the nav-link 'button' should change when it's completed, but since I can't access the parent of a CSS-selected element I need to make these changes directly to the 'menu-number' span element, including a 'nav-link' sized background colour. So I've made the menu-number the same size as the containing 'nav-link' . But when I add a background colour to the 'menu-number' , the text in the second is obscured.
How can I 'move' the second span in front of the first so I can see its text?
I have also tried making both spans position absolute or position relative and used z-index but this pulls the spans out of the flow of the document and means the width of the menu collapses. I can't set the width to a hard-coded value because the menu toggles open and closed, width-wise, (without a class being set) and the toggled width is set by javascript which, again, I can't access.
I have also tried using display: flex on the 'a' element and reversing the 'order' of span elements. No luck.
In semi-desperation I have tried setting the direction property on 'nav-link' to rtl. No luck.
I think I've tried a couple other things too, but at this point I'll wrap this question up.
Any pointers, much appreciated...
.menu-number {
border: none;
border-left: 10px solid transparent;
border-radius: 0px;
padding-top: 13px;
padding-left: 20px;
height: 45px;
position: absolute;
width: 100%;
text-align: left;
z-index: 100;
float: left;
}
.menu-number + span {
/*position: absolute;*/
padding-left: 40px;
z-index: 200;
}
.completed-section {
color: #42bb76 !important;
border-left: 10px solid #42bb76;
background-color: #274d56;
text-decoration: underline;
}
.nav-link > div > a {
display: flex;
*/flex-direction: row-reverse;*/
}
.nav-link > div > a > span:nth-of-type(1) {
order: 2;
}
.nav-link > div > a > span:nth-of-type(2) {
order: 1;
}
.nav-link > div > a > .section-name {
color: white;
padding: 13px 20px 0px 60px;
height: 45px;
float: left;
}
<div class="nav-link">
<div>
<a href="scroll/to/section">
<span class="menu-number completed-section">1.</span>
<span class="section-name">Section name</span>
</a>
</div>
</div>
I've also tried 'flex-direction' but I've now commented that out.

You can achieve this using CSS order property:
Here is the fiddle:
.menu-number {
order: 2;
}
.section-name {
order: 1;
}
.nav-link a{
display: flex;
}
<div class="nav-link">
<div>
<a href="scroll/to/section">
<span class="menu-number completed-section">1.</span>
<span class="section-name">Section name</span>
</a>
</div>
</div>

Related

How to change only the default cursor?

I have a custom cursor image for my website, but only for the default status. In the rest of cases (specially for text) I want the predefined ones.
But if I define the custom cursor this way...
html {
cursor: url('path/to/custom/cursor.svg') 0 0, default;
}
at least text status is lost (not pointer, but I suspect others have been lost as well) and my paragraphs, spans with text, headers, etc. show now my custom cursor instead of the predefined text selector one.
Of course, I could redefine styles for certain elements...
p, span, ol, ul, h1, h2, h3, h4 {
cursor: text;
}
but text status is not really linked to certain html tags, it appears when there's a text node not affected by other modifiers. For example, how can I target a div with only text, but exclude a div that contains just another div of certain color, background, etc.?
As I see in this question there's not a way to target text nodes directly, so I want to know if there's a less invasive way to define a custom cursor only in the case where the predefined default one would appear, and still showing all the predefined cursors by every modified state (text, scroll, etc.)
Thank you in advance.
Example 1: if html cursor defined, all is overridden:
html {
cursor: all-scroll;
}
Lorem ipsum dolor sit amet
Example 2: if we try to redefine some elements, we have now false positives...
html {
cursor: all-scroll;
}
/* Dillema: Which elements should be redefined to target predefined text status?? */
div {
cursor: text;
}
<div>Lorem ipsum dolor sit amet</div>
<div style="width: 100px; height: 100px; background-color: red;"></div>
TL;DR;
You can't strictly change the meaning of cursor: default; but you can style any element setting its cursor as desired.
So if you mean to address some particular elements or element types in general, you should select them pinpointing the elements with a fine grained selector (like: .classname{cursor: all-scroll;} or elementtype{cursor: all-scroll;}) but there's no selectors for element having a given property set at a given value.
If you want to get wild you may do in js:
//for every single element in the dom,
document.querySelectorAll('*')
//sets the cursor property to all-scroll if its current value is default
.foreach(el=>{ if (el.style.cursor === 'default') el.style.cursor = 'pointer'})
to set the style property of every single html element in the document that it will take the max priority.
But to just take them all via css this will be enough *{cursor: pointer;}
If you do html{cursor: all-scroll;} you won't be granted that every single elements will be styled like that because some element types don't inherit the cursor property value from its parent/ancestor and when the mouse will be over it, its style will take the precedence over the underlying html "canvas".
Anyway at a bare minimum you should set the html height at 100% in that case to make sure that that rule at least will trigger when no other element on the top layer where overriding the behaviour.
In my demo I show the 2 strategies at play and I easily demo the fact that form elements don't inherit from the parent ancestor and that when the rule is applied with *, it takes it all.
The whole story:
Here's the mdn docs about the cursor css property:
https://developer.mozilla.org/en-US/docs/Web/CSS/cursor
The cursor CSS property sets the mouse cursor, if any, to show when
the mouse pointer is over an element.
The cursor setting should inform users of the mouse operations that
can be performed at the current location, including: text selection,
activating help or context menus, copying content, resizing tables,
and so on. You can specify either the type of cursor using a keyword,
or load a specific icon to use (with optional fallback images and
mandatory keyword as a final fallback).
It's clear that such property will affect the cursor when the mouse pointer is over the element styled like that. So to affect every elements under the root umbrella it's enough to style the whole <html> element but it's also important to make sure the visible height covers the actual viewport!
That's why it was a solution to use html { height: 100% } for example.
It should be noted that an html document has always a root element and that's <html>. Any text content is always a textNode and anywhere you find it inside the page is always the content of some node and at worst it's a child node in the body element. All I said so far it's maybe ignoring text coming from the content css property (but let's pretend it doesn't exist).
So of course you can't style the text itself but you can style the element containing it, since there's always such an element, therefor there's always a selector you can use to style a given text that for sure will be contained in some element that you can address. The only concern is that you CAN'T limit the styling to the text alone, but to the whole content of the element you are going to style.
Now the only added thing to know is that some elements will have some default values for some css properties that will override any value set on a parent element. That's because of how css specifity works and how some properties get inherited from the ancestors.
I made a demo that includes several html element types.
Plus there are two buttons:
Toggle custom cursor on html - That will toggle the css class
custom .customcursor on the html element (the rule is predefined in the document as .customcursor{cursor: all-scroll !important;})
Toggle custom cursor on * - That will add/remove a css rule that will set the cursor css property to ALL elements in the DOM (*{cursor: all-scroll !important; .. the reason why I behaved this way is to leave to css the responsability to select ALL the elements instead of using js with querySelectorAll)
It's worth pointing out that I used !important to show off that it won't be enough to override the cursor property for those element types that don't inherit from parent.
When you'll set the customcursor on html you'll see that mostly
all the elements take the customization except the form elements.
When you'll set the rule that targets ALL the elements, it will
affect EVERYTHING and that cursor will be the only one you'll see
while hovering on the whole page viewport.
//create the empty stylesheet on document loaded
var styleSheet;
document.addEventListener('DOMContentLoaded',()=>{
const styleEl = document.createElement('style');
document.head.appendChild(styleEl);
styleSheet = styleEl.sheet;
});
function toggleCustomCursorOnBody(btn){
const cb = btn.querySelector('input');
document.querySelector('html').classList.toggle('customcursor');
cb.checked = !cb.checked;
}
function toggleCssRuleOnAllElements(btn){
const cb = btn.querySelector('input');
if(!cb.checked)
addCssRule();
else
removeCssRule();
cb.checked = !cb.checked;
}
function addCssRule(){
styleSheet.insertRule('*{cursor: all-scroll !important;}', 0);
}
function removeCssRule(){
styleSheet.deleteRule(0);
}
html {
border: solid 18px purple; /*<--this is to show the size of the element we are setting cursor for! */
background: lightgoldenrodyellow;
height: calc(100% - 36px); /*<--this was what I pointed out in comments */
}
.customcursor{
cursor: all-scroll !important;
}
/*the following just to give consistence to the page elements*/
[data-label]::before{
content: attr(data-label);
padding-right: 1em;
font-weight: 600;
padding: 0 .2em;
font-size: 1rem;
background-color: #FECE44;
color: #333;
width: 100%;
max-height: 1.2rem;
}
.toggles{
margin: 0 auto 1em auto;
}
.toggle{
cursor: pointer;
padding: .5em 1em;
}
.toggle > input[type="checkbox"]{
pointer-events: none;
}
body{
font-size: 18px;
text-align: center;
}
*{
box-sizing: box-model;
border: dotted 1px lightgray;
}
.container,
form
{
display: flex;
flex-wrap: wrap;
justify-content: space-around;
gap: 2vmin;
}
body > .container{
margin-top: 2vh;
}
.container > h1,
.container > h2,
.container > h3,
.container > h4,
.container > h5,
.container > h6
{
margin: 0;
max-height: 10vh;
}
.container > h1{
background: rgba(204, 204, 204, 1);
}
.container > h2{
background: rgba(204, 204, 204, 0.9);
}
.container > h3{
background: rgba(204, 204, 204, 0.8);
}
.container > h4{
background: rgba(204, 204, 204, 0.7);
}
.container > h5{
background: rgba(204, 204, 204, 0.6);
}
.container > h6{
background: rgba(204, 204, 204, 0.5);
}
.container > p{
background-color: lime;
font-size: 2rem;
margin: 0;
}
.container > ol{
background-color: cyan;
font-size: 1rem;
padding: .5em 1em .5em 1.5em;
margin: 0;
height: fit-content;
}
.container > a{
background: antiquewhite;
font-size: 2rem;
height: fit-content;
margin: 0;
}
.container > div:not(.container):not(.unstyled) {
width: 20vw;
height: 5vh;
background: dodgerblue;
color: white;
padding: 1em;
font-weight: 600;
font-size: 1.5rem;
display: flex;
justify-content: center;
align-items: center;
}
.container > span {
width: 20vw;
height: 5vh;
background: cadetblue;
color: white;
padding: 1em;
font-weight: 600;
font-size: 1.5rem;
display: flex;
justify-content: center;
align-items: center;
}
.container > textarea{
width: 15ch;
height: 10vh;
}
.container > label{
outline: solid 1px gray;
padding: .2em 1em;
background: gray;
color: white;
max-height: 1em;
}
.container > select{
max-height: 2em;
}
.container > input{
}
.container > input[type="text"]{
width: 15ch;
max-height: 1em;
font-size: 1rem;
padding: .5rem .5rem;
}
.unstyled input[type="checkbox"]{
position: relative;
width: 2em;
height: 2em;
}
.unstyled input[type="checkbox"] + label{
}
<body>
<div class="toggles">
<button id="toggle1" class="toggle" onclick="toggleCustomCursorOnBody(this);">
Toggle custom cursor on <html>
<input type="checkbox">
</button>
<button id="toggle2" class="toggle" onclick="toggleCssRuleOnAllElements(this);">
Toggle custom cursor on *
<input type="checkbox">
</button>
</div>
[THIS IS A TEXT NODE HAVING FONT SIZE FROM BODY]
<div class="container">
<div class="container" data-label="headings">
<h1><h1></h1>
<h2><h2></h2>
<h3><h3></h3>
<h4><h4></h4>
<h5><h5></h5>
<h6><h6></h6>
</div>
<div class="container" data-label="contents">
<p><p></p>
<ol>
<li><ol> <li></li>
<li><ol> <li></li>
<li><ol> <li></li>
</ol>
<a>
</div>
<div class="container" data-label="layout">
<div><div></div>
<span><span></span>
</div>
<form class="container" data-label="form">
<label><label></label>
<input type="text" value="<input type=text>">
<textarea><textarea></textarea>
<div class="unstyled">
<input type="checkbox">
<label><input cb></label>
</div>
<select>
<option disabled selected><select>...</option>
<option value="1">Option1</option>
<option value="2">Option2</option>
<option value="3">Option3</option>
</select>
<fieldset>
<legend><legend></legend>
<div>
<input type="radio" checked>
<label><radio></label>
</div>
<div>
<input type="radio" checked>
<label><radio></label>
</div>
<div>
<input type="radio" checked>
<label><radio></label>
</div>
</fieldset>
</form>
</div>
</body>

Hiding pseudo css element when data attribute is empty

I have the following badge that I can add to any element:
.notification-badge {
position: relative;
}
.notification-badge:after {
content:attr(data-badge);
position:absolute;
top:-10px;
right:-10px;
min-width: 10px;
padding: 3px 7px;
font-size: 12px;
font-weight: 700;
line-height: 1;
background-color: $brand-danger;
color: #fff;
text-align: center;
white-space: nowrap;
vertical-align: middle;
border-radius: 10px;
border: 2px solid #fff;
}
It's fairly straightforward, the element that I attach the badge class onto provides a data-badge attribute with some number, which gets shoved into the :after element's content.
I would like the badge to not appear at all if content is empty. I've tried using the :empty selector, but it doesn't work because the actual tag may still contain other elements, for instance:
<a href="/cart" class="notification-badge" data-badge="">
<i class="fa fa-shopping-cart"></i>
</a>
In this case, I'd want the shopping cart icon and link to still exist, but have the notification-badge class not render the badge.
So, I suppose I could give up on the idea of it being a pure pseudo element and just make it a span with the number inside of it instead of a data- attribute, but it seems like there is probably an easy way to do this that I'm just not aware of.
This works for me:
.notification-badge:after {
visibility: hidden;
}
.notification-badge[data-badge]:after {
visibility: visible;
}
The :empty selector selector matches every element that has no children (including text nodes) W3Schools
So what you could do is here do something like this:
.notification-bade .fa-shopping-cart {visibility:visible}
.notification-badge:after {
content:attr(data-badge); visibility: hidden
}

Strange behaviour when using text-align justify/text-justify and right

I ran into one IE-specific problem that I just can't wrap my head around.
The following HTML and CSS can be seen live in this pen.
:: HTML
<div id="container">
<div class="dummy">Dummy</div>
<nav>
<div id="right">
<ul>
<li>Lorem ipsum <img src="http://placehold.it/80x40"> dolor sit amet.</li>
<li>Anal natrach, ut vas petat, <img src="http://placehold.it/80x40"> doriel dienve.</li>
</ul>
<div class="dummy">Dummy</div>
<div class="dummy">Dummy</div>
</div>
</nav>
</div>
:: CSS
/* RESET */
* { margin: 0; padding: 0; vertical-align: top; }
ul { list-style: none; }
/* MARKUP */
#container {
line-height: 0;
font-size: 0rem;
text-align: justify;
text-justify: distribute-all-lines;
}
#container:after {
content: '';
display: inline-block;
width: 100%;
}
#container > * {
display: inline-block;
line-height: 1;
font-size: 1rem;
text-align: left;
text-justify: none; /* does not work */
}
#container nav {
text-align: right;
}
#right > * {
display: inline-block;
}
/* COLORS & STUFF */
#container { padding: 10px; background: #cfc; }
.dummy { padding: 10px; background: #ffc; }
#container nav { padding: 10px; background: #ccf; }
ul { padding: 10px; background: #fcc; }
So, what's the Problem?
The content of the green div is justified, while each child of the very div in turn is given text-align: left;. Those children are: the left dummy div and the bluish nav.
The nav contains a list (red), and two dummies. For the red list's items the text-align is set to right - and there's lies the problem (or at least, there you can see it).
The first image is shifted to the left (and thus overlays/hides some piece of the text). The second image (and thus the whole second list item) is fine. This, however, changes, when changing the text. It seems as if only the image of the longest (meaning widest) item stays where it should be - all other images (if you were to create some more items) are shifted - depending on the list item's width, that is.
Now, why is that so - and how can I fix it?
The following things I found out so far:
When setting the li { text-align: left; } the image stays fine in between the two text portions - but I don't get right alignment, of course.
When removing text-justify from the #container the image stays fine as well.
Setting text-justify either to auto or to none does not seem to work...
Once again: this is just regarding Internet Explorer (9+).
// EDIT
In order to avoid your time being spent on something I'm not interested in, I'll post something more on what I'd like to have.
The final code must
keep the current/desired functionality (i.e., justified alignment);
work in all major browsers (current version and at least one before that).
The final code must not
contain floats;
contain absolute/relative positions.
// EDIT
Here is a screenshot of the desired result (Firefox), and one of what I get in IE...
Change your text-justify to distribute (Tested in IE10, IE9, Chrome, FF):
text-justify: distribute;
Check out the codepen to see it in action.
Did you try by setting like this?
li img{display: inline-block; margin: 0 5px;} /*you could set margin: 1px; only*/
your code pen

How do I align text vertically when it is not in a table cell? [duplicate]

This question already has answers here:
Vertical Alignment
(4 answers)
Closed 9 years ago.
I am working on a mobile site and I have a couple of pages that display a small thumbnail with text to the right: http://sunsetwesterngardencollection.com/mobile/the-collection
The thumbnail positions well, but the text is challenged. I did some research and found one option but it does not seem to work properly.
Here is the HTML for the content:
<ul id="plants">
<li class="plant">
<a href="http://sunsetwesterngardencollection.com/mobile/plant/amistad-salvia"><img src="http://sunsetwesterngardencollection.com/photos/thumbnails/salvia_amistad_thumb.jpg" alt="‘Amistad’ Salvia" />
<span class="plant-name">‘Amistad’ Salvia</span></a>
<div class="orange-slice"></div>
</li>
<li class="plant">
<a href="http://sunsetwesterngardencollection.com/mobile/plant/black-adder-phormium"><img src="http://sunsetwesterngardencollection.com/photos/thumbnails/phormium_black_adder_thumb.jpg" alt="‘Black Adder’ Phormium" />
<span class="plant-name">‘Black Adder’ Phormium</span></a>
<div class="orange-slice"></div>
</li>
<li class="plant">
<a href="http://sunsetwesterngardencollection.com/mobile/plant/blue-riding-hood-penstemon"><img src="http://sunsetwesterngardencollection.com/photos/thumbnails/penstemon_blue_riding_hood_thumb.jpg" alt="‘Blue Riding Hood’ Penstemon" />
<span class="plant-name">‘Blue Riding Hood’ Penstemon</span></a>
<div class="orange-slice"></div>
</li>
</ul>
Here is the CSS:
ul#plants li {
width: 100%;
height: auto;
position: relative;
}
.orange-slice {
width: 100%;
height: 2px;
clear: both;
background: #e1562e;
}
ul#plants li img { float: left; width: 20%; margin: 0; }
ul#plants li span,
ul#plants li span a:link,
ul#plants li span a:visited {
color: #e1562e;
font-size: 1.3em;
font-weight: 500;
position: absolute;
top: 25%;
left: 23%;
text-transform: uppercase;
display: table-cell;
vertical-align: middle;
}
What is the proper way to align text vertically when it is not in a table cell?
Thanks!
You make the line-height the same as the height of the element the text is in.
YOU DON'T NEED JAVASCRIPT DO THIS!
So after looking over your code I have a solution along with a couple suggestions.
First lets take a look at what your can do to solve this problem:
Let add the following to your css to make the list items act like tables.
#plant.plants { display: table;}
After that lets focus on your containing anchor:
#plant.plants a { display: table-row;}
And finally let's attack the span in which you have said text:
#plant.plants a span { display: table-cell;}
Remove the following rules you have currently on said span
//remove
position: absolute;
top: 25%;
left: 23%;
Now this is going to look a little funky but you can adjust your row by changing your image width. Now onto a suggestion I have, granted I'm not sure if your using 'orange-slice' for a interactive type drop down. But if your just utilizing for stylist purposes I would suggest just adding:
#plant.plants { border-bottom: 2px solid #e1562e; }

Understanding CSS sprites and links

I have been researching how to use CSS sprites as image links, but I can't figure this out. I have a PNG (here: ) that has two images in it (for simplicity). I want each image to be act as an icon that can be linked to an external website (Twitter and Facebook). I set up my CSS like this:
CSS
#authorpage-links ul {
list-style-type:none;
}
#authorpage-links ul li {
background: url("/links-authorpage1.png") no-repeat scroll 0 0 transparent;
}
#authorpage-links ul li.twitter {
background: url("/links-authorpage1.png") no-repeat 0 0;
width: 20px;
height: 14px;
}
#authorpage-links ul li.facebook {
background: url("/links-authorpage1.png") no-repeat -21px 0;
width: 14px;
height: 14px;
}
...and my HTML like this:
HTML
<ul id="authorpage-links">
<li id="authorpage-links" class="twitter">
<a target="_blank" href="http://twitter.com/"></a>
</li>
<li id="authorpage-links" class="facebook">
<a target="_blank" href="http://facebook.com/"></a>
</li>
</ul>
Now, 2 questions:
1) Is using a list to display these images the best way or should I use div's?
2) Is this an issue with my CSS IDs and classes?
Any help is greatly appreciated.
Based on a revision of your CSS (problems that I'll come to, later) to the following:
#authorpage-list {
list-style-type: none;
}
#authorpage-list li {
float: left;
}
#authorpage-list li a {
background-color: transparent; /* I broke the background down into individual parts */
background-image: url(http://i.stack.imgur.com/ta3Va.png);
background-position: 0 0;
background-repeat: no-repeat;
width: 15px;
height: 15px;
display: block; /* in order that the a elements could be assigned a width/height */
border: 1px solid #f90; /* for diagnostic purposes while working on this, adjust to taste */
}
#authorpage-list #authorpage-facebook-link a {
/* a specific selector, in order to be more specific than the previous
selector which styled the defaults for the a elements in this position */
background-position: -21px 0;
}​
And amending your HTML to the following:
<ul id="authorpage-list">
<li id="authorpage-twitter-link" class="twitter">
<a target="_blank" href="http://twitter.com/"></a>
</li>
<li id="authorpage-facebook-link" class="facebook">
<a target="_blank" href="http://facebook.com/"></a>
</li>
</ul>
I came up with this: JS Fiddle demo.
​
CSS problems
This is the biggest no-no insofar as HTML goes (or so far as I've ever been able to see, it's even worse than the blink tag): you have multiple examples of the same id in your HTML. An id must be unique within the document. If not, you have invalid HTML. Which causes problems with CSS, with JavaScript and...it's just bad.
If you have multiple elements that need to share a property/style, or whatever, use a class, not an id.
Your selectors. #authorpage-links ul should match a ul element within an ancestor element of id="#authorpage-links". The ul is the element with that id. I'll ignore that its child elements also had that id, since I think I've covered that part. All your other CSS started off that base, which wasn't accurate, and so didn't work.
Your <li> elements may be sized to 14x14, but you've got nothing in the <a> tags, so those'll shrink down to a 0x0 area, effectively making your list elements clickable areas invisible. You should probably put a space into the anchor tag, so there's SOMETHING to push them open, e.g.
<a target="_blank" href="http://facebook.com/"> </a>
^^^^^^
Your a link need to have a size. I did so in making the a's have a clickable area. Since your lis don't need a size i gave the size to the a links.
Replace your li css with:
ul#authorpage-links li a {
display: inline-block;
background: url("/links-authorpage1.png") no-repeat scroll 0 0 transparent;
}
ul#authorpage-links li.twitter a {
background-position: 0 0;
width: 20px;
height: 14px;
}
ul#authorpage-links li.facebook a {
background-position -21px 0;
width: 14px;
height: 14px;
}
Also remove the id attribute from your lis.
"... fantastic answer ..." - Sparky672

Resources