CSS: Change parent on focus of child
Solution 1
You can now do this in pure CSS, so no JavaScript needed 😁
The new CSS pseudo-class :focus-within
would help for cases like this and will help with accessibility when people use tabbing for navigating, common when using screen readers.
.parent:focus-within {
border: 1px solid #000;
}
The :focus-within pseudo-class matches elements that either themselves match :focus or that have descendants which match :focus.
Can I use...
You can check which browsers support this by visiting http://caniuse.com/#search=focus-within
Demo
fieldset {
padding: 0 24px 24px !important;
}
fieldset legend {
opacity: 0;
padding: 0 8px;
width: auto;
}
fieldset:focus-within {
border: 1px solid #000;
}
fieldset:focus-within legend {
opacity: 1;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<form>
<fieldset>
<legend>Parent Element</legend>
<div class="form-group">
<label for="name">Name:</label>
<input class="form-control" id="name" placeholder="Enter name">
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" class="form-control" id="email" placeholder="Enter email">
</div>
</fieldset>
</form>
</div>
Solution 2
There is no chance how to do that with CSS. CSS can style only siblings, children, etc. not parents.
You can use simply JS like this:
<style>
.parent {background: green}
.focused {background: red;}
</style>
<div class="parent">
<input class="childInput" type="text" />
<div class="sibling"></div>
</div>
<script>
$('.parent > *')
.focus(function() {
$('.parent').addClass('focused');
})
.blur(function() {
$('.parent').removeClass('focused');
});
</script>
This code takes all direct children of .parent
and if you focus one of them, class focused
is added to parent. On blur, this class is removed.
Solution 3
You can use pure CSS to make the text input look like it's not a text input unless it is in focus
http://jsfiddle.net/michaelburtonray/C4bZ6/13/
input[type="text"] {
border-color: transparent;
transition-duration: 600ms;
cursor: pointer;
outline-style: none;
text-overflow: ellipsis;
}
input[type="text"]:focus {
border-color: initial;
cursor: auto;
transition-duration: 300ms;
}
Solution 4
Try the contenteditible attribute. This may require more work to turn it into usable form data however.
http://jsfiddle.net/michaelburtonray/C4bZ6/20/
<span class="parent" contenteditable>Click me</span>
Related videos on Youtube
AaronF
Updated on December 09, 2021Comments
-
AaronF over 2 years
Let's say you have something like:
<div class="parent"> <input class="childInput" type="text" /> <div class="sibling"></div> </div>
I want to change the appearance of the parent/siblings when the child receives focus. Are there any CSS tricks for doing stuff like this?
Edit:
The reason for my question is as follows:
I'm creating an Angular app which needs editable text fields. It should look like a label until it is clicked, at which point it should look like a normal text input. I styled the text field based on :focus to achieve this effect, but the text is cut off by text input's boundaries. I also used ng-show, ng-hide, ng-blur, ng-keypress and ng-click to switch between the label and the text input based on blurs, key presses and clicks. This worked fine except for one thing: After the label's ng-click="setEdit(this, $event)" changes the edit boolean used by ng-show and ng-hide to true, it uses a jQuery call to .select() the text input. However, it isn't until after the completion of the ng-click that everything is $digest'd, so the text input loses focus again. Since the text input never actually receives focus, using ng-blur to revert back to showing the label is buggy: The user has to click in the text input and then click out of it again to revert back to showing the label.
Edit:
Here's an example plunk of the issue: http://plnkr.co/edit/synSIP?p=preview
-
Andi almost 10 yearsjavascript is no option?
-
Tushar almost 10 yearsThis can't be done using only CSS, you need to use js.
-
AaronF almost 10 yearsIt is, but I was curious if it can be done with styling. I'll add an edit to get into the reason for my question.
-
haim770 almost 10 yearsParent matching can't be done using CSS only. Siblings matching can be done only if the element is adjacent to the defining element. See developer.mozilla.org/en-US/docs/Web/CSS/…
-
MickyScion almost 10 yearssee this stackoverflow.com/questions/14402514/… it is the same problem
-
-
AaronF almost 10 yearsThanks for your answer. I added an edit regarding the reason for my question: I wanted to switch between the label and the input on focus/blur, and was having some issues doing this in Angular.
-
AaronF almost 10 yearsThanks. I actually tried that, but ran into some issues: "...I styled the text field based on :focus to achieve this effect, but the text is cut off by text input's boundaries...". Showing an ellipsis is definitely better than clipping, but I'd like to see the whole thing, if possible. A related question I just asked is here: stackoverflow.com/questions/24289266/…, if you're interested.
-
AaronF almost 10 yearsUseful, to be sure. Unfortunately, our client base requires the use of non-HTML5-compliant browsers.
-
Jamie Carter about 6 yearsseriously amazing!
-
Mike Aron about 5 yearsIE should kicked away. R.I.P
-
MrVanilla over 4 yearsThis is not vanilla JS, this is using jQuery.
-
Anurag Hazra over 4 yearshere's the browser support: caniuse.com/#search=focus-within
-
Anurag Hazra over 4 yearswhopps! did not noticed it. sorry.
-
J J B over 4 years@AnuragHazra No problem. I updated the post to make it more clear now and to include an image of the browser support table.
-
Yehya over 3 yearsGreat!! you're a lifesaver ;)
-
Aamir Afridi over 2 yearscan you imagine how easy this makes the developers life
-
BalB about 2 yearsYou saved the day!