CSS: Change parent on focus of child

90,308

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>

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

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>
Share:
90,308

Related videos on Youtube

AaronF
Author by

AaronF

Updated on December 09, 2021

Comments

  • AaronF
    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
      Andi almost 10 years
      javascript is no option?
    • Tushar
      Tushar almost 10 years
      This can't be done using only CSS, you need to use js.
    • AaronF
      AaronF almost 10 years
      It 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
      haim770 almost 10 years
      Parent 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
      MickyScion almost 10 years
      see this stackoverflow.com/questions/14402514/… it is the same problem
  • AaronF
    AaronF almost 10 years
    Thanks 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
    AaronF almost 10 years
    Thanks. 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
    AaronF almost 10 years
    Useful, to be sure. Unfortunately, our client base requires the use of non-HTML5-compliant browsers.
  • Jamie Carter
    Jamie Carter about 6 years
    seriously amazing!
  • Mike Aron
    Mike Aron about 5 years
    IE should kicked away. R.I.P
  • MrVanilla
    MrVanilla over 4 years
    This is not vanilla JS, this is using jQuery.
  • Anurag Hazra
    Anurag Hazra over 4 years
    here's the browser support: caniuse.com/#search=focus-within
  • Anurag Hazra
    Anurag Hazra over 4 years
    whopps! did not noticed it. sorry.
  • J J B
    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
    Yehya over 3 years
    Great!! you're a lifesaver ;)
  • Aamir Afridi
    Aamir Afridi over 2 years
    can you imagine how easy this makes the developers life
  • BalB
    BalB about 2 years
    You saved the day!