Dave Sag
Dave Sag

Reputation: 13486

How to constrain CSS to when a contained input has focus?

Assume I have a form input structured as follows:

<div class="wrapper">
  <span class="icon icon-search"></span>
  <input type="text"/>
</div>

is there a way, with CSS3, to apply a red border around the .wrapper div on a focus state on the input element?

.wrapper input:focus {
  border solid thin red;
}

puts the border on the input field but I want it on the containing div.

Upvotes: 1

Views: 417

Answers (3)

Johannes
Johannes

Reputation: 67738

There is a relatively new selector in CSS, ":has()". It selects a parent div if the element in the parenthesis is present, or if you add a pseudo selector to that element, if that condition applies.

In your example .wrapper:has(input:focus) selects the wrapper when the input is focused. You might want to add outline: none; and border: none; to prevent the default focus effect of the browser and to make the input border disppear when focused.

.wrapper:has(input:focus) {
  display: inline-block;
  border: 2px solid red;
}

input {
  width: 100px;
  height: 30px;
  font-size: 18px;
}

input:focus {
  outline: none;
  border: none;
}
<div class="wrapper">

  <span class="icon icon-search"></span>
  <input type="text" /> </div>

Upvotes: 0

Steve Schrab
Steve Schrab

Reputation: 395

Using :focus-within should do the trick. It will trigger anytime an element inside of it has focus.

.wrapper:focus-within {
  border: 1px solid red;
}

Read more here: https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-within

Upvotes: 0

lukek
lukek

Reputation: 478

You're looking for a css parent selector. Unfortunately that isn't currently available. The exact functionality you're looking for would need JavaScript or alternative HTML.

It looks like you want the border to surround the icon and the field but currently it is only surrounding the field? My suggestion would be to use the sibling selector like so: (From my example below i've moved the icon after the input)

* {
    box-sizing: border-box; /* Helps with sizing calculations */
}
.wrapper {
    position: relative;
}
.icon {
    width: 20px;
    height: 20px;
    position: absolute;
    background-color: blue;
    left: 200px;
    top: 0;
    border: solid 1px transparent;
    border-left: none;
}
input {
    width: 200px;
    height: 20px;
    border: solid 1px blue;
    border-right: none;
}
input:focus {
    border-color: red;
    outline: 0;
}
input:focus + .icon {
  border-color: red;
}
<div class="wrapper">
  <input type="text"/>
  <span class="icon icon-search"></span>
</div>

Upvotes: 2

Related Questions