not of nth child selector not working in sass - css

I am trying to apply certain styles to all items in list besides the first child. I think I set up the sass correctly, however the style is not being applied currently.
html
<div class="list">
<div *ngFor="let item of data; index as i; first as isFirst; last as isLast"class="list-item">
<input class="radio" name="radio" type="radio" />
<label for="radio1">Buttom</label>
</div>
</div>
sass
.list label:not(:nth-of-type(1))::before{
background-color:blue;
}

You can achieve this doing by all the items bg blue and the first one's bg to white or whatever your background is.
<div class="list">
<div *ngFor="let item of data; let i=index" [class.first]="i === 0">
<input class="radio" name="radio" type="radio" />
<label for="radio1" class="lbl">{{item.name}}</label>
and your css should be like this:
label {
background-color:blue;
}
.first label {
background-color: #fff;
}
I assume your data is like that:
data = [
{name: "car"},
{name: "truck"},
{name: "bike"}
]
This is working example

If you mean selecting all .list-item except the first one, the CSS will be like:
.list-item:not(:nth-of-type(1))::before {
content: '';
background-color:blue;
}
Since you are using pseudo element ::before, you may want to use content: '' to specify some content, otherwise background-color will has no effect.

Related

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>

How to change style based on sibling child attribute

I'm working with Vuetify and Stylus on this snipped of HTML
<div class="input-group input-group--dirty input-group--text-field">
<label>Language</label>
<div class="input-group__input">
<input readonly="readonly" type="text"/>
</div>
<div class="input-group__details"></div>
</div>
Is there a CSS/Stylus way to edit input-group__details based on what the status of input[readonly] is?
Something like:
if (.input-group > input has readonly)
.input-group__details
height: 0px
else
.input-group__details
height: 5px
Basically, how do I change a class based on the sibling's child attribute?
Unfortunately as of now, this cannot be achieved in CSS, and as all CSS preprocessors need to generate CSS, it also cannot be done with any pre- or post-processing whatsoever.
You will either have to change your HTML structure (make sure the targeted element comes after the readonly input, and they share the parent element), or resort to Javascript.
If you have enough time, you can also wait for selectors level 4 to arrive.
which would solve your problem with this
.input-group__input:has(input[readonly]) + .input-group__details { ... }
Well not possible with the provided markup, but if you allowed to change some markup you can get this...try to make the .input-group__details next sibling of input..
Also you don't need to assign a value to readonly...just use readonly
input[readonly]+.input-group__details {
color: red;
}
<div class="input-group input-group--dirty input-group--text-field">
<label>Language</label>
<input class="input-group__input" type="text" readonly />
<div class="input-group__details">Welcome</div>
</div>
<br>
<div class="input-group input-group--dirty input-group--text-field">
<label>Language</label>
<input class="input-group__input" type="text" />
<div class="input-group__details">Welcome</div>
</div>
You can bind class.
<div class="input-group input-group--dirty input-group--text-field" :class="'className': trueFalse">
<label>Language</label>
<div class="input-group__input">
<input readonly="readonly" type="text"/>
</div>
<div class="input-group__details"></div>
</div>
Now in your vue script:
data: {
trueFalse: false,
},
methods: {
someClassName() {
//condition of your input field
//if condition true make 'trueFalse' to true else to false
this.trueFalse = true
}
}
at last in your css:
.className {
//add your style with !important
}

CSS Parent Class over other CSS Classes

My Code Looks something like this:
input{
...
}
label{
...
}
<div class="textfield 1">
<input tpye="text" id="fullname">
<label for="fullname">Name</label>
</div>
<div class="textfield 2">
<input tpye="text" id="fullname">
<label for="fullname">Name</label>
</div>
<div class="textfield 3">
<input tpye="text" id="fullname">
<label for="fullname">Name</label>
</div>
now i want to apply the css only on one of the textfields and because the code is way to long to ad a ".textfield1" to every css element i want to ask if i can create a "parent class element" like:
.textfield1{
input{
...
}
label{
...
}
}
.textfield2{
input{
...
}
label{
...
}
}
It's like putting the styled elements in a Folder.
Is there a way to do that?
Thanks a lot in advance!
You can use:
.textfield1 input {
...
}
.textfield1 label {
...
}
Check this link for more CSS selectors combinations: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors
As Turnip mentions in comments, you cannot have spaces in classnames. So instead of having class names such as textfield 1, you could have them like textfield1 - or something else. For the time being, I am using textfield1 to demonstrate the solution.
Now, you could use the descendant selector .textfield1 input (notice the space between the class name and tag name) or the child selector .textfield2 > input (notice the arrow > between the class name and tag name) to specify that given CSS rule must apply only to the descendants or children of given class.
input{
border: 2px solid blue;
}
label{
color: blue;
}
.textfield1 input {
border: 2px solid red;
}
.textfield2 > input {
border: 2px solid yellow;
}
<div class="textfield1">
<input tpye="text" id="fullname">
<label for="fullname">Name</label>
</div>
<div class="textfield2">
<input tpye="text" id="fullname">
<label for="fullname">Name</label>
</div>
<div class="textfield3">
<input tpye="text" id="fullname">
<label for="fullname">Name</label>
</div>
If you use preprocessor like Sass or Less, you can nasted css like your example. It's not possible in the classical way.
In css:
.textfield2 input{
...
}
.textfield1 input{
...
}
.textfield1 label, //<- if the label style of textfield1 and textefield2 are same
.textfield2 label{
...
}
Be careful, in your HTML you have a space between textfield and the number <div class="textfield 3">. That's mean your div has the CSS class textfield and the CSS class 3.
If you just want one class remove the space and the code above works.
If you keep the space, just modify .textfield2 to .textfield.2 with a dot between textfield and the number (to indicate that the style it's for the class textfield with the class 2)

CSS/SASS previous child selection

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;
}

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');
}
});

Resources