CSS/SASS previous child selection - css

I'm trying to make a span background change colors when I focus on an input field. The HTML is as follows:
<div class='parentDiv'>
<span class='spanClass'>Some text</span>
<input class='inputClass' type='text' />
</div>
The closest I could come to something that does this is using the + adjacent sibling selector and doing something like this:
input:focus + span {
background-color: red;
}
But it doesn't quite work because span must come after input. Is there some way for me to make the span background change colors when I focus the input field?

Normally, you would need JS to do that. Here's an example using JS that keeps styling in your CSS:
(function() {
var spanEl = document.querySelector('.parentDiv > .spanClass');
var inputEl = document.querySelector('.parentDiv > .inputClass');
// Add "highlighted" class to "spanClass" element on focus event
inputEl.addEventListener('focus', function() {
spanEl.classList.add('highlighted');
});
// Remove "highlighted" class from "spanClass" element on blur event (un-focus)
inputEl.addEventListener('blur', function() {
spanEl.classList.remove('highlighted');
});
})();
.spanClass.highlighted {
background-color: red;
}
<div class="parentDiv">
<span class="spanClass">Some text</span>
<input class="inputClass" type="text" />
</div>
In your example, though, you could simply float the one element to the left and change the order in the HTML.
.parentDiv { overflow: hidden; }
.spanClass { float: left; }
.inputClass:focus + .spanClass {
background-color: red;
}
<div class="parentDiv">
<input class="inputClass" type="text" />
<span class="spanClass">Some text</span>
</div>
Something to note for the future, though:
The :has() "relational pseudo-class" seems to be in the works for "CSS4". You can also track it here: http://caniuse.com/#feat=css-has
This means that you will (hopefully) be able to do this eventually:
.spanClass:has(+ .inputClass) {
background-color: red;
}

Related

CSS - How to remove text off a screen when a checkbox is selected

I want to remove text off the screen when a checkbox is selected using CSS. I want to know if there's a way of doing this through CSS. Here's some code
<form>
<input id="check" type="checkbox">
</form>
<p> sample text </p>
How do I remove the sample text when the checkbox is selected. I want to achieve this by using CSS.
UPDATE
It's not possible to do it through CSS, so can you tell me if there's a way to do this through JS.
If you can change the HTML to
<form>
<input id="check" type="checkbox">
<p>sample text</p>
</form>
You could use adjacent sibling selector and the checked pseudo class.
/* Remove entire p */
input:checked + p { display:none; }
/* Resize the font to zero */
input:checked + p { font-size: 0; }
/* Indent the text so it is offscreen */
input:checked + p { text-indent: -9999px; }
You can actually achieve this result if you are able to change your structure a bit. You will need to put input and p tag together in the same div so we can target them with CSS.
html:
<form>
<input id="check" type="checkbox">
<p class="hello"> sample text </p>
</form>
css:
input[type="checkbox"]:checked + p {
display:none
}
Here's a solution with JavaScript:
func = () => {
if(document.querySelector("input").checked) {
document.querySelector("p").style.display = "none";
} else {
document.querySelector("p").style.display = "block";
}
}
<form>
<input id="check" type="checkbox" onchange="func()">
</form>
<p>Some Text</p>
Make a little change in your HTML:
<form>
<input id="check" type="checkbox">
<p id="home"> sample text </p> <!-- added an id to the p tag -->
</form>
Create a JavaScript file, lets say 'main.js', inside write the code:
function change() {
var decider = document.getElementById('check');
if(decider.checked){
document.getElementById('home').innerHTML = "";
}
}
Add a script tag to link your JS file to the HTML:
<script type="text/javascript" src="main.js"></script>

CSS change label background of another element, when radio button is checked

I want to change the background color of the label class 'label-status', depending on if the radio button is set to agree or disagree.
<div class="testclass">
<label class="label-status">Status</label>
<label class="radio-inline" style="display:inline-block;"><input type="radio" name="status" disabled="">Agree</label>
<label class="radio-inline" style="display:inline-block;"><input type="radio" name="status" checked="" disabled="">Disagree</label>
</div>
Since it's not my website, but some custom user CSS I want to inject to make it more usable, I cannot make any changes to the actual html.
Thanks for your answers in advance.
You can take advantage of the order property (Flexbox or Grid) together with the for attribute to link the label with the related input element:
.testclass {display: flex} /* displays flex-items (children) inline; can also use the "inline-flex" which only takes the content's width */
.label-status {order: -1} /* puts it back to the desired place (above other siblings); the initial value is set to 0 */
.testclass > input:first-of-type:checked ~ .label-status {background: green}
.testclass > input:last-of-type:checked ~ .label-status {background: red}
<div class="testclass">
<input type="radio" name="status" id="agree">
<label for="agree">Agree</label>
<input type="radio" name="status" id="disagree" checked>
<label for="disagree">Disagree</label>
<label class="label-status">Status</label> <!-- needs to be placed below other siblings in order to take advantage of the "~" selector -->
</div>
Then you can use the general sibling combinator ~ to target the .label-status with e.g. :first-of-type & :last-of-type selectors set on the input elements, of course in conjunction with the :checked pseudo-class selector.
You could use JS, like so:
$(document).ready(function() {
$(".label-status").on("click",function() {
if($(this).find('input[type="radio"]').is(':checked')) {
$('.radio-inline').removeClass('sel_bk_color');
$(this).addClass('sel_bk_color');
}
});
});
Here is an example of this kind of thing in action: https://jsfiddle.net/tr9Lyxz3/1/
By default your inputs are disabled. you have to first remove disable property and then add onclick attributes to run a function which will change background color.
document.getElementsByName('status')[0].removeAttribute("disabled")
document.getElementsByName('status')[1].removeAttribute("disabled")
document.getElementsByClassName('radio-inline')[0].setAttribute("onclick","myFunction()")
document.getElementsByClassName('radio-inline')[1].setAttribute("onclick","myFunction()")
function myFunction(){
if (document.getElementsByName('status')[1].checked) {
document.getElementsByClassName("label-status")[0].classList.remove("myclass2")
document.getElementsByClassName("label-status")[0].classList.add("myclass1");
}
else if (document.getElementsByName('status')[0].checked) {
document.getElementsByClassName("label-status")[0].classList.remove("myclass1")
document.getElementsByClassName("label-status")[0].classList.add("myclass2");
}
}
you have to define your css for myclass1 and myclass2 as per your background color requirement.
this is not possible using pure css as you cant read values dynamically using css. so if you can use js then this will solve your problem without editing html.
Some pure CSS solutions seem to miss the you are not allowed to change the HTML.
Are you allowed to use javascript?
Here is some javascript without JQuery:
var updateLabel = function(e) {
var label = document.getElementsByClassName("label-status")[0];
if (e.target !== e.currentTarget && event.target.type === "radio") {
if(e.target.labels[0].innerText === "Agree") {
label.style.background = "green"
} else {
label.style.background = "red";
}
}
e.stopPropagation();
}
var wrapperElement = document.getElementsByClassName("testclass")[0];
wrapperElement.addEventListener("click", updateLabel, false);
https://codepen.io/anon/pen/MXWJXK
You do have to remove the disabled attribute from your radio buttons. With javascript you can use element.removeAttribute("disabled").
https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute
.buttons {
display: flex
align-item: center;
}
.condition {
padding-right: 50px;
}
.status {
order: -1;
padding: 5px;
border: 2px solid #000;
color: #fff;
}
.buttons > input:first-of-type:checked ~ .status {
background: green;
}
.buttons > input:last-of-type:checked ~ .status {
background: red;
}
<div class="buttons">
<input type="radio" name="status" id="agree">
<label for="agree" class="condition">Agree</label>
<input type="radio" name="status" id="disagree" checked>
<label for="disagree" class="condition">Disagree</label>
<label class="status">Status</label>
</div>

CSS focus. Can't get it to change a label field

I am trying to get a focus on a field change the color of a text, but whatever I try: it is not working. Below is the HTML:
.register-section input:focus + .register-section label[for=signup_username] {
color: #ffffff !important;
}
<div class="register-section" id="basic-details-section">
<h4>Account Details</h4>
<label for="signup_username">Username (required)</label>
<input type="text" name="signup_username" id="signup_username" value="" />
</div>
Can anyone tell me what I'm doing wrong?
Thanks in advance!
The + adjacency operator can only be used to select DOM nodes following the initial selector (CSS selectors can only resolve in this direction). As such, because your label is before your input in your html, you cannot select it on the :focus state of the input using CSS.
To fix this, you will need to change your HTML to reverse the order of the elements, and adjust your CSS to change their display order, then select as appropriate:
.register-section label[for=signup_username] {
float: left;
}
.register-section input:focus + label[for=signup_username] {
color: #ffffff !important;
}
<div class="register-section" id="basic-details-section">
<h4>Account Details</h4>
<input type="text" name="signup_username" id="signup_username" value="" />
<label for="signup_username">Username (required)</label>
</div>
An alternative for those who wish to achieve the same result using jQuery, target the focus and blur events of the input field to change the color of the label:
$('#signup_username').on('focus blur', function(e){
var label = $("label[for=signup_username]");
if (e.type == 'focus'){
label.css('color','#FFF');
}
else {
label.css('color','#000');
}
});
See JSFiddle

add background color to a div when radio button is checked using css

I have a radio button and I need to add a style to its parent div when the radio button is checked. This I need to do only with css. In the below html, if the radio is checked, i need to apply a color to the div "options"
HTML
<div class="options">
<span class="option_radio">
<input type="radio" name="payMethod" id="payMethod1" value="aaa" >
</span>
<span class="option_image">
<label for="payMethod1">
<img src="abc.png" >
</label>
</span>
</div>
I tried the below approaches but its not coming correctly
.options input[type="radio"]:checked span{
background-color:black;
}
.options input[type="radio"]:checked div.options{
background-color:black;
}
could somebody please help me on this
Sorry, can't do that yet. You can only go down the tree, not up it. You will either need to make the elements you want to style siblings or descendents of the radio button. Ancestor selectors do not yet exist:
http://css-tricks.com/parent-selectors-in-css/
<input type="radio" name="payMethod" id="payMethod1" value="aaa" />
<div class="options">
<span class="option_radio">
</span>
<span class="option_image">
<label for="payMethod1">
<img src="abc.png" />
</label>
</span>
</div>
css
input[type='radio']:checked + div.options {
background-color:green;
}
input[type='radio']:checked + div.options span {
background-color:red;
}
That would require using parent selectors from CSS4 http://www.w3.org/TR/selectors4/ Unfortunately CSS4 is not yet available. So for today it is not possible to do that using pure css.
Javascript is your answer. Provided Vanilla and jQuery examples.
var payMethod = document.querySelector('#payMethod1');
payMethod.onchange = function() {
alert('clicked')
// Get span and div
if(this.checked) {
var elements = document.querySelectorAll('.option_radio, .options');
// Loop elements & add class
for(var i = 0; i < elements.length; i++) {
if (elements[i].classList)
elements[i].classList.add("checked");
else
elements[i].className += ' checked';
}
}
};
//jQuery implementation
$('#payMethod1').change(function() {
if($(this).is(':checked')) {
$('.option_radio, .options').addClass('checked');
}
});

I am trying to target/select elements in a different parent with CSS

Take a look at the code below...
As you can see the 'HAZEL(NUT)' and 'HASSEL(NØD)' has a different parent to the checkbox. Which is why I think the checkbox works for the font-weight part, but doesn't work for selecting #hazelnut or #hasselnod. If anyone could help me with the correct selector for #hazelnut and #hasselnod I would be very grateful.
Hope this is clear, I'm quite a newbie to HTML and CSS, so have trouble explaining what I mean sometimes!
HTML here:
<div class="container" id="lang">
<input type="radio" id="english" name="language" value="english" checked="checked" />
<input type="radio" id="dansk" name="language" value="dansk" />
<ul>
<label for="english"><li id="en">ENGLISH</li></label>
<label for="dansk"><li id="dk">DANSK</li></label>
</ul>
</div>
<div class="container" id="myname">
<h1 id="hazelnut">HAZEL<br>(NUT)</h1>
<h1 id="hasselnod">HASSEL<br>(NØD)</h1>
</div>
CSS here:
#dansk:checked ~ * #dk {
font-weight: 700;
}
#dansk:checked ~ * #en {
cursor: pointer;
}
#dansk:checked * #hazelnut {
display: none;
}
#english:checked ~ * #en {
font-weight: 700;
}
#english:checked ~ * #dk {
cursor: pointer;
}
#english:checked * #hasselnod {
display: none;
}
Many thanks!
In CSS, for the ~ selector to work, the elements must have the same parent. As I see it, I'm afraid you'll have to involve some javascript in here.
What I'd do, is have the radio buttons change a data attribute of #lang, so it would be transparent to the css:
<div id="lang" data-value="en">
and then use the following css rules:
/*when #myname is preceded by #lang with data-value attribute 'en',
select direct child #hasselnod */
#lang[data-value='en'] ~ #myname > #hasselnod {
/* and set its display to none*/
display: none;
}
Now, we'll need the javascript to change the data-value attribute of #lang. Look at the onclick function in the following snippet:
<input type="radio" id="dansk" name="language" value="dansk"
onclick="this.parentNode.setAttribute('data-value', 'da')" />
Check out this fiddle: http://jsfiddle.net/wkL7q/2/
To target elements in a different parent, I think you need to use jQuery:
$("#lang input").change(function () {
var lang = $(this).val();
if(lang == 'dansk') {
$('#hazelnut').hide();
$('#hasselnod').show();
} else {
$('#hazelnut').show();
$('#hasselnod').hide();
}
});
Check out this fiddle: http://jsfiddle.net/X3ZtK/

Resources