Selecting the next sibling, only if this span is showing - html

I need to give a certain span a specific color, but only when it's previous sibling has "display: block". I don't have direct access to the HTML so this are the only classes I can work with.
<div class="price-content">
<span class="old-price">
**<span class="new-price>**
<span class="percentage">
</div>
I have this all over the page repeating, "old-price" is hidden by default. But sometimes it has "display: block". How can I give "new-price" a specific color, only when "old-price" is displaying?

Using jQuery, look for all the .old-price elements. If they've got display:block, then modify their sibling .new-price element. Here's an example:
$(document).ready(function() {
$.each($('.price-content > .old-price'), function(i, el) {
$oldPrice = $(el);
if ($oldPrice.css('display') === 'block') {
$oldPrice.next('.new-price').css('color', 'purple');
// Or maybe do 'addClass' for semantic's sake
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="price-content">
<span class="old-price" style="display: none">$5.98</span>
<span class="new-price">$5.15</span>
<span class="percentage">14%</span>
</div>
<hr />
<div class="price-content">
<span class="old-price" style="display: block">$5.98</span>
<span class="new-price">$5.15</span>
<span class="percentage">14%</span>
</div>

AFAIK, you need JavaScript to do this. A simple solution would be to add a new class that represents whether the .old-price element is display: block (called block below).
.old-price.block + .new-price {
color: red;
}
<div class="price-content">
<span class="old-price block">OLD PRICE</span>
<span class="new-price">NEW PRICE</span>
<span class="percentage">%</span>
</div>

Related

unable to remove css of span class due to $(...).css is not a function

I am trying to change the css of a html given a span class.
I have an html as follows:
<form id=thing>
<div id=a>
<span class=x>
</span>
</div>
<div id=b>
<span class=x>
</span>
</div>
</form>
When I inspect the webpage I see the following style being applied:
#thing .x {
display: none !important;
}
Now my goal is to get rid of this display css property completely.
I tried $("#thing .x").css("display", ""); but i keep getting "$(...).css is not a function - unable to remove css "
Any tips on how to solve this?
Using inline style with setAttribute()
I assume you are trying to remove the styling for display from none. '' => nothing would not be a valid style to use, use a valid property value recognized by the display property, like inline or block for example.
You can override the !important rule set in CSS with the same CSS hack used in inline style as inline style takes presidence over styles set in CSS sheet. The only way I was able to do it was by setting the style attribute using el.setAttribute('style', 'display: inline !important;'). See snippit and a few examples of failure and finally success below...
let dontUseImportant = document.querySelectorAll('#thing .x')
dontUseImportant.forEach(el => {
// style display inline !important is ignored
// this is likely a rule in JS that will disallow
// spaces in values passed into properties for style
// more research on this may be fruitful
// however note the outcome in console.log
el.style.display = "inline !important";
el.textContent = 'this will not parse to DOM'
console.log(el)
})
dontUseImportant.forEach(el => {
// style display is added but is over written by !important used in CSS
el.style.display = "inline";
el.textContent = 'this will not parse to DOM'
console.log(el)
})
// this also will not work
dontUseImportant.forEach(el => {
el.setAttribute('style', 'display: null !important;');
el.textContent = 'this will not parse to DOM'
console.log(el)
})
// by adding !important using setAttribute behind our
// property, this affects the elements style
// however, we are putting a bandaid on a bandaid
dontUseImportant.forEach(el => {
el.setAttribute('style', 'display: inline !important;');
el.textContent = 'content x is finally shown!'
console.log(el)
})
#thing .x {
display: none !important;
}
.y {
display: inline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="thing">
<div id="a">content a
<span class="x">content x
</span>
</div>
<div id="b">content b
<span class="x">content x
</span>
</div>
</form>
Swapping classes on element
Because the CSS file is using !important this unfortunately will override any styles you place on the element using el.style.property = '' regardless of using JS or a JS library like JQuery.
You could add a new class using JS that has a defining display: inline and then remove the old class. Keep in mind that you must add a valid property value when using styles. display = '' is not valid.
Your particular issue is a great example as to why !important is a BAD IDEA for styling as a crutch!
let $dontUseImportant = $('#thing .x')
// iterate over elements and swap out the classes
// make sure to add the new class 'y' first
// then remove initial class 'x'
$.each($dontUseImportant, function(i){
$(this).addClass('y')
$(this).removeClass('x')
console.log($dontUseImportant[i])
})
#thing .x {
display: none !important;
}
.y {
display: inline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="thing">
<div id="a">content a
<span class="x" >content x
</span>
</div>
<div id="b">content b
<span class="x">content x
</span>
</div>
</form>
Why not using the hidden attribute? It is supported in all modern browsers. So in your case, you don't even need CSS.
jQuery:
$('button').on('click', function() {
$('.x').each(function() {
$(this).show();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="thing">
<div id="a">
<span class="x" hidden>
1
</span>
</div>
<div id="b">
<span class="x" hidden>
2
</span>
</div>
</form>
<button>Show</button>
Vanilla JS
const x = document.querySelectorAll('.x');
document.querySelector('button').addEventListener('click', (e) => {
for (let item of x) {
item.removeAttribute('hidden');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="thing">
<div id="a">
<span class="x" hidden>
1
</span>
</div>
<div id="b">
<span class="x" hidden>
2
</span>
</div>
</form>
<button>Show</button>

CSS only - same width for multiple <span> elements, based on the largest

I'm curious if there is a way to set the width property for multiple <span> elements to the same value if they are not siblings to each other. The width should be based on the largest
span element.
The expected result would be something like a table where the left text will automatically grow.
So instead of this:
Text: Value
Larger Text: Value
I want it like this:
Text: Value
Larger Text: Value
I know this can be done with JavaScript (see example at the end), but I want to know if this is possible with CSS only.
And at best without changing the HTML structure, but I'm open for such an answer as well.
Some similar questions I've found, but they are about direct sibling spans. So it's not really fitting in my case:
Make adjacent sibling elements same width using only CSS
How can I make multiple spans equal width within a div
Why I want a CSS only solution and no JS?
Because I have to loop those elements twice:
To determine which of those elements is the largest and get the width from it
To set all elements the same width
Here is the working example with JS:
const variantNames = document.querySelectorAll('.variant-name');
let greatestWidth = 0;
variantNames.forEach( (name) =>
{
if(name.offsetWidth > greatestWidth)
{
greatestWidth = name.offsetWidth;
}
});
variantNames.forEach( (name) =>
{
name.style.width = greatestWidth + 'px';
});
.container,
.variant {
width: 100%;
}
.variant-name {
display: inline-block;
margin-right: 5px;
}
<div class="container">
<div class="variant">
<span class="variant-name">Size:</span>
<span>28</span>
</div>
<div class="variant">
<span class="variant-name">Waterproof:</span>
<span>Yes</span>
</div>
<div class="variant">
<span class="variant-name">Color:</span>
<span>Azure</span>
</div>
</div>
Easiest solution, that will work with the HTML structure you have - format the whole thing as a table.
.container {
display: table;
}
.container .variant {
display: table-row;
}
.container .variant span {
display: table-cell;
}
<div class="container">
<div class="variant">
<span class="variant-name">Size:</span>
<span>28</span>
</div>
<div class="variant">
<span class="variant-name">Waterproof:</span>
<span>Yes</span>
</div>
<div class="variant">
<span class="variant-name">Color:</span>
<span>Azure</span>
</div>
</div>

How to move one HTML element below another with CSS

I am working with a 3rd party support provider and am trying to work around some limitations around what can be customized. I would like to add an HTML element (a) below a label, but only have access to css and footer html. My current idea is to add a hidden anchor in the footer and then try to reposition it via the css. I guess this MIGHT be possible with flexboxes, but my css foo is not that strong. So I figured I would come here and see if there was any way around it.
Concretely, I have a multiline textbox where users will enter their support request, and I need to insert an href to what can be asked right above it. I already have a ::before in place for some basic helper text, but I know that you cannot insert markup using css...thus my current attempt.
Is this even possible without knowing the specific location of each item...only their respective identifiers?
Here is a jsfiddle that reproduces the page as minimized as I can get it.
Again, please note that I ONLY have the ability to add HTML to the bottom of the page (in the footer element), and a global css file (shown in the separate css). That means I cannot edit the html outside the footer - that would be too easy ;)
HTML
<html id="portal_html"><head>
</head>
<body>
<div id="container">
<portal>
<div data-id="ticketForm" id="layoutContainer">
<div>
<div>
<div><h2>Submit a ticket</h2></div>
<div id="field_description">
<label for="description"><!-- react-text: 1235 -->Description<!-- /react-text --></label>
<div>
<div>
<div data-id="description">
<div id="description"><iframe name="deskEditor_New"></iframe></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<footer id="footerContainer"><div id="footerContainer"><div class="Footer__footerCopyrigt">
<div class="Footer__container2">
<span>Powered by </span>
<a rel="noopener noreferrer" href="supporturl" target="_blank" class="Footer__footerLink">Support Provider</a>
<span> | </span>
<a rel="noopener noreferrer" href="terms" target="_blank" class="Footer__footerLink">Terms of Service</a>
<span> | </span>
<a rel="noopener noreferrer" href="privacy" target="_blank" class="Footer__footerLink">Privacy Policy</a>
<a rel="noopener noreferrer" href="foo">target</a>
</div>
</div>
</div></footer></portal></div></body></html>
and current css:
.ticketDetail .ConversationForm__list+.ConversationForm__list { display:none; }
div[data-id="description"]::before {
content: "Some custom content";
font-size: smaller;
}
label[for="description"], a[href="foo"]{
order:-1;
}
body {
display:flex;
flex-direction:column;
}
UPDATE
I found this SO that sadly shows flexbox will not work because they are not in the same heirarchy :/
....so I believe the answer is that this is not possible :(
Can you use JS?
const textAreaWrapper = document.querySelector('.text')
const linky = document.querySelector('[href=linky]')
document.body.insertBefore(linky, textAreaWrapper)
.someclass {
display: block;
}
.rest {
display: block;
}
.text {
display: block;
}
<span class="someclass">
<label>foo</label>
</span>
<span class="text">
<textarea></textarea>
</span>
<label class="rest">more stuff</label>
<label class="rest">even more stuff</label>
Here is a link I want above the textarea

CSS : Selecting next elements with specific class

I have the following html code and I'm searching a way to select the span's elements identified by class="selection" only inside after a select element where id beginning with "cf-":
<select id="cf-1234567891322418287202826"></select>
<span class="select2 select2-container">
<span class="selection">
<span class="select2-selection"></span> // Apply CSS HERE
</span>
</span>
<select id="cf-8298298876787346863834334"></select>
<span class="select2 select2-container">
<span class="selection">
<span class="select2-selection"></span> // Apply CSS HERE
</span>
</span>
<select id="tu-656555"></select>
<span class="select2 select2-container">
<span class="selection">
<span class="select2-selection"></span> // DO NOT Apply CSS HERE
</span>
</span>
I tried the following code without any result. Where is my mistake ?
select[id^="cf-"] + span.select2-selection {
color: blue;
}
span.select2-selection is not a sibling of select[id^="cf-"] so you need to change that selector into
select[id^="cf-"] + span span.select2-selection {
...
}
since you are trying to match a span.select2-selection which is a child of a span element which is a sibling of select[id^="cf-"].
this should do it:
[id*="cf-"] .selection{
//css code here
}
additional info:
[id*="sometext"]
will select any element with id containing "sometext"
by putting a space after that you can specify a element within this element
doing .selection will select the element with class "selection" inside the element with id containing that tex

How do I change the color of a checkbox without changing it for the whole class?

I need to change the style of a checkbox label.
this is my html:
<div class="ui-checkbox">
<input id="keepMeInformed" type="checkbox" data-theme="d" onchange="fixCheckboxesValues();" checked="checked" value="1" name="optedIn">
<label class="optional ui-btn ui-btn-icon-left ui-btn-corner-all ui-btn-up-d ui-checkbox-off" for="keepMeInformed" data-theme="d">
<span class="ui-btn-inner ui-btn-corner-all" aria-hidden="true">
<span class="ui-btn-text">Label text</span>
<span class="ui-icon ui-icon-shadow ui-icon-checkbox-off"></span>
</span>
</label>
</div>
I need the text to be red but if I change the .ui-btn-text class style all the buttons of the page will get the red text style.
.ui-btn-text{
color:red;
}
Is there a way to change only the color of the label in the checkbox?
Edit:
thanks guys I solved the problem adding a div that wrapped the CheckBox and wrote jQuery:
function changeCheckBoxStyle() {
$('#checkBoxWrapper').find('[class=ui-btn-text]').css('color','red');
}
but I think that scott's solution works ok too :) thanks
Assuming you are using ID's correctly (unique to a page) then this should work:
#keepMeInformed + label .ui-btn-text {
color: red;
}
It looks for the unique input element keepMeInformed and then finds the sibling label element next to it and applies the style to that label's .ui-btn-text class element only.