CSS: Change parent on focus of child

JavascriptHtmlCssAngularjsFocus

Javascript Problem Overview


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

Javascript Solutions


Solution 1 - Javascript

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 - Javascript

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>

http://jsfiddle.net/C4bZ6/

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 - Javascript

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 - Javascript

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>

Solution 5 - Javascript

You can style it even for focus-within and not(focus-within) like this (without using JavaScript => more accessible and faster):

        .myform:not(:focus-within) button[type="submit"] {
            display: none;
        }

        .myform:focus-within button[type="submit"] {
            display: block;
        }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAaronFView Question on Stackoverflow
Solution 1 - JavascriptJ J BView Answer on Stackoverflow
Solution 2 - JavascriptpavelView Answer on Stackoverflow
Solution 3 - JavascriptMichaelView Answer on Stackoverflow
Solution 4 - JavascriptMichaelView Answer on Stackoverflow
Solution 5 - JavascriptMarkus BrunnerView Answer on Stackoverflow