0

Given the following design:enter image description here

I'd like to hide the 'magnifier' icon and show the 'close' X icon in case the the input's placeholder is not shown.

My markup is:

input:not(:placeholder-shown) {
   // hide 'magnifier' icon
   // show 'close' icon
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet"/>
<div class="input-group input-group-sm w-50" id="search-box">
  <div class="input-group-prepend">
     <span class="input-group-text bg-white" id="input-magnifier">
        <i class="fa fa-search text-muted"></i>
     </span>
     <span class="input-group-text bg-white">
        <i class="fa fa-close text-muted"></i>
     </span>
  </div>

  <input type="search" placeholder="Search with &#39;exact match&#39;" class="form-control" />

  <div class="input-group-append">
    <div class="dropdown btn-group" role="group">
        <button class="btn btn-light btn-sm dropdown-toggle" data-toggle="dropdown" aria-expanded="false" type="button">filters</button>            
    </div>
  </div>
</div>

How to make this input group behave in that way? Or in another words, how do I access the icons from my input element in Scss?

TylerH
  • 20,799
  • 66
  • 75
  • 101
fer
  • 1,016
  • 1
  • 10
  • 20

1 Answers1

2

Due to the way CSS works, there is no way to do this without javascript given your current html markup. CSS sibling and adjacent selectors can only select elements that come after a given element, because css "cascades" through the markup from top to bottom.

That said, if you switch around your markup you can absolutely achieve this. Luckily, the input-group class already has display:flex;, so if you move the children elements, you can still control the display order with the order property.

Then all you need to do is use the + (adjacent) selector. See the attached code.

/* CSS adjacent selectors used here, to select the prepend
   class only when the placeholder is shown or not shown */

input:not(:placeholder-shown)+.input-group-prepend #input-magnifier {
  display: none;
}

input:placeholder-shown+.input-group-prepend #input-delete {
  display: none;
}


/* This is the code used to reorder the elements so that
   the buttons still appear before the input */

.input-group-prepend {
  order: -1;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet" />
<div class="input-group input-group-sm w-50" id="search-box">


  <input type="search" placeholder="Search with &#39;exact match&#39;" class="form-control" />

  <!-- moved .input-group-prepend div to here so that the adjacent selector works -->
  <div class="input-group-prepend">
    <span class="input-group-text bg-white" id="input-magnifier">
        <i class="fa fa-search text-muted"></i>
     </span>
    <span class="input-group-text bg-white" id="input-delete">
        <i class="fa fa-close text-muted"></i>
     </span>
  </div>

  <div class="input-group-append">
    <div class="dropdown btn-group" role="group">
      <button class="btn btn-light btn-sm dropdown-toggle" data-toggle="dropdown" aria-expanded="false" type="button">filters</button>
    </div>
  </div>
</div>
Clay
  • 36
  • 4