How to take an element from the next level of nesting - html

I have this structure generated by WordPress plugin:
<span>
<input/>
</span>
<label></label>
I need to write my css like this:
input:focus+label {
color: #1743fc;
transform: translateY(1rem) translateX(0.5rem);
}
But the "+" and "~" rules don't work. How can i do this?

You can use :has() now in some browsers:
span:has(input:focus) + label {
color: #1743fc;
transform: translateY(1rem) translateX(0.5rem);
}

input:focus+label {
color: #1743fc;
transform: translateY(1rem) translateX(0.5rem);
}

Related

Change another Tag Css When input Has Value

i have this tags in to my project, but i want to change css placeholder tag color and size ... style when my input has value.
i want To Use :valid in css but I will not succeed.
tip: my HTML Tags Structure Cant Change
<div class="wrapper">
<input type="text" required>
</div>
<span class="placeholder">E-Mail</span>
my Css:
.wrapper {
position: relative;
}
input {
font-size: 14px;
height: 40px;
}
.placeholder {
position: absolute;
font-size: 16px;
pointer-events: none;
left: 1px;
top: 2px;
transition: 0.1s ease all;
}
input:focus~.placeholder {
top: -1px;
font-size: 11px;
}
input[value=""]~.placeholder {
top: -1px;
font-size: 11px;
}
This can't be done purely through CSS with any amount of cross-browser compatibility (yet), because the element you want to style is not a sibling, or the descendant of a sibling, of the element the changed style is a response to.
There are a couple of ways, though, if JavaScript is an option:
// simple named function to determine if the <input> element (evt.currentTarget)
// has a valid value:
const hasValue = (evt) => {
// caching the current <input> element to which the event-handler is bound:
let target = evt.currentTarget;
// navigating to the closest ancestor element with a class of 'wrapper',
// using the Element.classList API to toggle the class of 'childInputHasValue'
// on the element based on whether the <input> has a valid value, in that it
// matches the regular expression in the 'pattern' attribute:
target.closest('.wrapper').classList.toggle('childInputHasValue', target.validity.valid)
},
// retrieving all <input> elements with a type attribute equal to 'text':
inputs = document.querySelectorAll('input[type=text]');
// iterating over the <input> elements using an anonymous Arrow function with
// NodeList.prototype.forEach():
inputs.forEach(
// binding the 'hasValue' function as the event-handler for the 'input' event
// on each of the <input> elements:
(el) => el.addEventListener('input', hasValue)
);
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.placeholder {
color: crimson;
}
.wrapper.childInputHasValue + .placeholder {
color: lime;
}
<div class="wrapper">
<input type="text" required pattern="^[a-zA-Z0-9][a-zA-Z0-9\s]{5,20}$">
</div>
<span class="placeholder">E-Mail</span>
JS Fiddle demo.
Alternatively, if you're able to adjust your HTML to the following this can be done – quite easily – with CSS:
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.placeholder {
color: crimson
}
input[type=text]:valid + .placeholder {
color: lime;
}
<div class="wrapper">
<input type="text" required pattern="^[a-zA-Z0-9][a-zA-Z0-9\s]{5,20}$">
<span class="placeholder">E-Mail</span>
</div>
JS Fiddle demo.
However, if you're okay with (currently) poor cross-browser performance (as I write this :has() is available only in Safari and behind the "Experimental Web Platform features" flag in Chrome and Chromium), possibly using a JS shim if necessary, then you may be able to use the :has() selector:
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.placeholder {
color: crimson;
}
.wrapper:has(input:valid) + .placeholder {
color: lime;
}
<div class="wrapper">
<input type="text" required pattern="^[a-zA-Z0-9][a-zA-Z0-9\s]{5,20}$">
</div>
<span class="placeholder">E-Mail</span>
JS Fiddle demo.
As for using :has() with a shim, that could be as simple as follows:
// here we check if the browser supports the ':has(input:valid)' selector, note that this is achieved
// by passing the 'selector(...)' CSS function into the CSS.supports() method with the selector for
// which we're assessing support:
if (!CSS.supports('selector(:has(input:valid))')) {
const hasValue = (evt) => {
let target = evt.currentTarget;
target.closest('.wrapper').classList.toggle('childInputHasValue', target.validity.valid);
},
inputs = document.querySelectorAll('input[type=text]');
inputs.forEach(
(el) => el.addEventListener('input', hasValue)
);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.placeholder {
color: crimson;
}
/* this selector will be used by browsers that understand, and
implement, the ':has(...)' selector, and discarded by others: */
.wrapper:has(input:valid) + .placeholder {
color: lime;
}
/* this selector will take advantage of the classes/approach
implemented by JavaScript: */
.wrapper.childInputHasValue + .placeholder {
color: lime;
}
<div class="wrapper">
<input type="text" required pattern="^[a-zA-Z0-9][a-zA-Z0-9\s]{5,20}$">
</div>
<span class="placeholder">E-Mail</span>
JS Fiddle demo.
References:
CSS:
Adjacent-sibling (+) combinator.
:has() (compatibility).
#supports.
HTML:
pattern attribute.
required attribute.
JavaScript:
Arrow functions.
CSS.supports().
document.querySelectorAll().
Element.classList.
Element.closest().
EventTarget.addEventListener().
I don't think it's possible by CSS only. You have to add a toggle class on the parent wrapper when input is focused, then there will add a class like active in the wrapper and you could write CSS like-
wrapper.active ~ .placeholder {
top: -1px;
font-size: 11px;
}

Using the CSS checkbox hack, how can I affect more than one element when :checked? [duplicate]

This question already has answers here:
Is there a "previous sibling" selector?
(30 answers)
What does the "~" (tilde/squiggle/twiddle) CSS selector mean?
(3 answers)
What does the "+" (plus sign) CSS selector mean?
(9 answers)
CSS transform doesn't work on inline elements
(2 answers)
Closed 1 year ago.
I currently have something like this
on jsfiddle
HTML:
.ln-header {
cursor: pointer;
}
.ln-header::after {
content: "+";
margin-left: 10px;
transition: 400ms;
}
.list-wrap {
display: none;
}
.checkbox1:checked + .list-wrap {
display: block;
}
.checkbox1:checked + .ln-header::after {
transform: rotate(45deg);
}
.checkbox1:checked + .ln-wrap::after {
transform: rotate(45deg);
}
.checkbox1 {
display: none;
}
<div>
<div>
<label for="list1" class="localnav-categories-label">
<span class="ln-header">categories</span>
</label>
<input type="checkbox" id="list1" class="checkbox1">
<nav class="list-wrap">
<ul>
<li>
one
</li>
<li>
two
</li>
</ul>
</nav>
</div>
</div>
I'm trying to get the plus sign (as an ::after element) to rotate, preferably with an animation, while a list pops up. Currently, I am only able to get the list to appear, while the plus sign remains static. I've heard about the checkbox only affecting its sibling element (may be wrong), but after playing around with the location, where I have it now seems to be the only place that it'll work for the list to appear.
How could I make it so that when I check the checkbox, both the list appears and the '+' rotates simultaneously?
Thanks!
First, you need to bring <input type="checkbox" id="list1" class="checkbox1"> to the front of anything you want to control the style of, since sibling selectors can only select forwards.
Second, you need to use ~ instead of + to select siblings that do not have to be right next to each other.
Third, you can't rotate an inline element(the default display of pseudo elements is inline), so you need to change the display of .ln-header::after to inline-block or inline-flex etc.
Finally, since .ln-header is a deeper element, you need to select it with a descendant selector .checkbox1:checked ~ * .ln-header::before
Then there you have it:
.ln-header {
cursor: pointer;
}
.ln-header::after {
content: "+";
margin-left: 10px;
transition: 400ms;
display: inline-block;
}
.list-wrap {
display: none;
}
.checkbox1:checked ~ .list-wrap {
display: block;
}
.checkbox1:checked ~ * .ln-header::after {
transform: rotate(45deg);
}
.checkbox1 {
display: none;
}
<div>
<div>
<input type="checkbox" id="list1" class="checkbox1">
<label for="list1" class="localnav-categories-label">
<span class="ln-header">categories</span>
</label>
<nav class="list-wrap">
<ul>
<li>
one
</li>
<li>
two
</li>
</ul>
</nav>
</div>
</div>

Apply CSS Style on all elements except with a SPECIFIC ID

CSS Code(what I need)
<style>
div[id!='div1']// I actually needed an inequality operator for NOT EQUAL TO
{
font-size:40px;
}
</style>
HTML code
<body>
<div>abc</div>
<div>def</div>
<div id='div1'>ghi</div>
</body>
The CSS didn't work as I intended.
I actually wanted to define the style for all <div>-elements except the one with id='div1'.
How can I do that?
Use the :not selector:
div:not(#bar){
color:red;
}
<div>foo</div>
<div id="bar">bar</div>
Update : name instead of ID:
div:not([name="bar"]){
color:red;
}
<div>foo</div>
<div name="bar">bar</div>
Update: CSS2 selector, similar answer to Tom Heard-s:
div{
color:red;
}
div[name="bar"]{
color:blue;
}
<div>foo</div>
<div name="bar">bar</div>
Also, see selectivizr
CSS3 solution:
div:not(#div1)
CSS2 solution:
div {
color: red;
}
div#div1 {
color: inherit;
}
By name:
CSS3 solution:
div:not([name=div1]) {
color: red;
}
CSS2 Solution (note not supported in IE6 - but who cares anymore):
div {
color: red;
}
div[name=div1] {
color: inherit;
}
If you are only to target browsers supporting CSS3 selectors you could do this:
div:not(#div1) {
...my styles...
}

How do I rotate individual letters and keep them flowing left-to-right?

I am trying to get a string with each individual letter rotated 90 degrees; however, I want to keep the "flow" of letters going left-to-right, not vertical. I also want to keep that "strikethrough" horizontal green line (see images below).
What's the simplest way to accomplish this? I prefer using JavaScript and/or CSS.
With the -transform: rotate CSS style I get the following:
<style type="text/css">
.rotate {
-webkit-transform: rotate(-90deg);
}
</style>
<body>
<div class="rotate">
<span style="color:#0C0; text-decoration:line-through;">
<span style="color:#000;">
A B C
</span></span></div>
What I would like to get is something like this, without resorting to a custom font.
Pure CSS:
<div class="letters">
<span>A</span><span>B</span><span>C</span>
</div>​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​
.letters {
height:8px;
line-height:16px;
border-bottom:1px solid green;
position:relative;
}
.letters > span {
float:left;
-webkit-transform: rotate(-90deg);
}​
Demo
Here's some js that should do the trick: http://jsfiddle.net/AYGDR/8/
$(function() {
$(".target").html(("<span>" + $(".target").html().split(" ").join("</span><span>") + "</span>"));
var rotate = 0;
$(".target span").each(function() {
rotate = rotate - 90
$(this).css({
"-webkit-transform": "rotate(" + rotate + "deg)",
"display": "inline-block"
});
});
});
And I accidentally threw in some bonus shifting rotation since I imagined that was part of the question.
my CSS:
<style>
span[class^="rot"]:not([char]):before{
content: '\27b7'; }
span[class^="rot"][char]:before{content: attr(char);}
span[class^="rot"] { position: relative; }
span[class^="rot"]:before {
position: relative; display: inline-block;
font-weight: bold; font-size: 16px; line-height:16px;
font-family: Tahoma, Verdana, sans-serif;
margin:0;padding:0;
width:16px;height:16px;
}
.rot-90:before { transform: rotate(-90deg); }
.rot90:before { transform: rotate(90deg); }
.rot45:before { transform: rotate(45deg); }
.rot-45:before { transform: rotate(-45deg); }
.rot180:before { transform: rotate(180deg); }
</style>
<p>
A long time <span class=rot90 style="color: green"></span> ago in a
<span class=rot-45 char="G"></span>alax<span class=rot180 char="y"></span>
<span class=rot-90 char="F"></span>ar far
a<span class=rot45 char="w"></span>way
This works in latest version of chrome
<span style="color:#000; display: inline-block; max-width: 10px;">
A B C
</span>
only wrote the innermost span though

Can you style an active form input's label with just CSS

Given the following html
<label for="inputelement">label</label>
<input type="text" id="inputelement" name="inputelement" />
You can style the input on focus using
input:focus { background: green; }
Is there a way of also styling the <label /> without JavaScript?
Thanks all
No. there is unfortunately no predecessor selector in css
input:focus -+ label { ... }
would be lovely.
having the label after the input would be dooable:
input:focus + label { ... }
you could use some positioning to display before...
For completeness, if your input field is within the label you can use focus-within:
HTML:
<label>
<input name="example" type="text">
</label>
CSS:
label:focus-within {
background: #DEF;
}
UPDATED
Make sure you check the draft as this may change: https://drafts.csswg.org/selectors-4/#relational
The :has() relational pseudo-class will allow the selection of parents for example, the following selector matches only <a> elements that contain an <img> child:
a:has(> img)
This can be combined with other selectors such as :focus, :active or :not to offer a lot of potential.
Unfortunately browser support isn’t great at the time of writing: https://caniuse.com/#feat=css-has
Adding this for people finding this page in the future. CSS4 will have a parent selector allowing you to choose what element to apply the style to:
I think the current spec allows you to specify which item is matched with a ! sign - the subject selector.
label! > input {
font-weight: bold;
}
This allows far greater control than just parent, for example in this scary chain below the p tag is the target!
article > h1 + section > p! > b > a {
font-style: italic;
}
You can use an attribute selector:
label[for=inputelement]:focus,
label[for=inputelement]:active {
/*styles here*/
}
Note that this isn't supported by IE6, but should work in all other browsers, including IE7 and IE8.
That will obviously only work for that specific ID. If you would like it to work for all IDs, simply leave out the ID:
label[for]:focus,
label[for]:active {
/*styles here*/
}
This will now work for all labels with a for attribute.
If you need something in between, you'll need to use classes.
You can, so long as the label follows the input in the Mark-up:
input:focus + label,
input:active + label {
/* style */
}
Okay the idea is to wrap the input, label, help, error etc. in a Flexbox Container.
Then use the + selector, to select the label element.
Note: it will work only when <label> comes after <input>
Then you define the <label> order by using the flexitem order property.
Sure you can also using classnames.
.container {
display: flex;
flex-direction: column;
}
input {
border: none;
}
label {
order: -1;
}
input:focus {
border: 1px solid red;
}
input:focus + label{
color: red;
}
<div class="container">
<input id="username" />
<label for="username">Username</label>
</div>
Yes, of course you can.
You'll need to:
Group both label and the form into a parent element (like a div)
Style the label with focus pseudo selector selector for the parent, ie .parent:focus label { color: green }
You can see a very minimal sample at jsfiddle I made.
<div class='workarea'>
<div class='hasinput'>
<label>Label 1 (should be green when active)</label>
<input />
</div>
<div class='hasinput'>
<label>Label 2 (should be green when active)</label>
<input />
</div>
</div>
.workarea {
max-width: 500px;
}
label,
input {
width: 100%;
}
.hasinput {
margin-bottom: 1rem;
}
.hasinput label {
color: blue;
}
.hasinput:focus-within label {
color: green;
}
Give your input button a style class
css style:
INPUT.book:hover, INPUT.book:focus:hover {
background-image:url(book_over.png);
background-repeat:no-repeat;
height: 40px;
width: 140px;
font-family:calibri, Tahoma;
font-size:20px;
color:#ffffff;
text-align: center;
font-weight: bold;
}
INPUT.book {
background-image:url(book_active.png);
background-repeat:no-repeat;
height: 40px;
width: 140px;
font-family:calibri, Tahoma;
font-size:20px;
color:#ffffff;
text-align: center;
font-weight: bold;
}
and the input html:
<input name="Bestil2" type="submit" class="book" value="Book møde" />
I haven't figured out yet, how to avoid grey background even though I have a transparent png file, maybe just an jpg will do. But I hope this helps.
Good luck :-)
Here is an alternative usign CSS grid:
As some sugested if the label is after the input then using flex or in my case using CSS grid you can place the label first.
body {
font-family: Arial;
}
.form-field {
display: grid;
gap: 4px;
}
.form-field label {
grid-row: 1;
font-size: 12px;
color: #737373;
}
.form-field input {
outline: unset;
border-radius: 6px;
padding: 6px 10px;
font-size: 14px;
border: 1px solid #737373;
}
.form-field input:focus {
border-color: #328dd2;
}
.form-field input:focus + label {
color: #328dd2;
}
<div class="form-field">
<input id="myinput" />
<label for="myinput">
My Input
</label>
</div>
This can be done if you target browsers that support flexbox - see this: http://plnkr.co/edit/g376cf38iphfvGfSubOz?p=preview
For brevity, the css there is minimal but you'll need some browser specific prefixes to extend support to somewhat older browsers.