0

I need a search icon before my input and because input doesn't have a ::before, I've opted to have the following markup:

<div id="demos-search-bar" class="col-md-12">
        <svg version="1.1" id="demos-search-icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
            viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
        <style type="text/css">
            .st0{fill:#3F3F3F;}
        </style>
        <path class="st0" d="M8,1c3.31,0,6,2.69,6,6c0,1.55-0.59,2.96-1.56,4.03l2.27,2.27c0.39,0.39,0.39,1.02,0,1.41
            C14.51,14.9,14.26,15,14,15s-0.51-0.1-0.71-0.29l-2.43-2.43C10.01,12.74,9.04,13,8,13c-3.31,0-6-2.69-6-6S4.69,1,8,1z M8,11
            c2.21,0,4-1.79,4-4c0-2.21-1.79-4-4-4S4,4.79,4,7C4,9.21,5.79,11,8,11z"/>
        </svg>
        <input type="text" id="demos-search" placeholder="Search...">
</div>

And because of this, I'm forced to use JS so that when the user clicks inside the wrapper demos-search-bar (maybe even on the icon itself), I can focus the actual input itself.

Problem is...it kinda...doesn't work. When I click anywhere outside the input itself (but not actually outside of the whole thing, on the body for example), it de-focuses for a second and then re-focuses properly, creating buggy behavior:

let demosSearch = $('#demos-search');

$('#demos-search-bar').on('click', () => {
  const demosSearchInput = $('#demos-search');

  if (demosSearchInput.is(':focus')) {} else {
    demosSearchInput.focus();
  }
});

demosSearch.focusin((focusEvent) => {
  $('#demos-search-bar').addClass('searching');
});

demosSearch.focusout((blurEvent) => {
  $('#demos-search-bar').removeClass('searching');
});
#demos-search-icon {
  display: flex;
  flex-grow: 0;
  width: 14px;
  height: 14px;
  margin-right: 8px;
}

#demos-search {
  display: flex;
  position: relative;
  flex-grow: 1;
  z-index: 2;
  margin: 0;
  border: 0;
  padding: 0;
  box-shadow: none;
}

#demos-search-bar {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  position: relative;
  z-index: 2;
  margin: 0;
  padding: 12px 16px;
  border: 2px solid rgba(0, 0, 0, 0.05);
  border-width: 0px 2px 2px 2px;
  transition: box-shadow 0.5s ease, padding 0.25s ease-in-out;
}

#demos-search-bar:hover {
  cursor: text;
}

#demos-search-bar.searching {
  -webkit-box-shadow: 0px 15px 50px 0px rgba(0, 0, 0, 0.1);
  -moz-box-shadow: 0px 15px 50px 0px rgba(0, 0, 0, 0.1);
  box-shadow: 0px 15px 50px 0px rgba(0, 0, 0, 0.1);
  padding: 12px 24px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="demos-search-bar" class="col-md-12">
  <svg version="1.1" id="demos-search-icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
            <style type="text/css">
                .st0{fill:#3F3F3F;}
            </style>
            <path class="st0" d="M8,1c3.31,0,6,2.69,6,6c0,1.55-0.59,2.96-1.56,4.03l2.27,2.27c0.39,0.39,0.39,1.02,0,1.41
                C14.51,14.9,14.26,15,14,15s-0.51-0.1-0.71-0.29l-2.43-2.43C10.01,12.74,9.04,13,8,13c-3.31,0-6-2.69-6-6S4.69,1,8,1z M8,11
                c2.21,0,4-1.79,4-4c0-2.21-1.79-4-4-4S4,4.79,4,7C4,9.21,5.79,11,8,11z"/>
            </svg>
  <input type="text" id="demos-search" placeholder="Search...">
</div>

What am I missing here?

2
  • Why not use the input background to display your icon? Or since you are apparently using bootstrap, use an input group with label? Both of those make things very simple and require no javascript. Commented Nov 21, 2019 at 17:58
  • @RobertMcKee I'm not aware of any techniques where I can put any image inside an input and also inputs don't have :before/:after. Commented Nov 21, 2019 at 17:59

1 Answer 1

3

Here is the background image technique:

input {
  background: url('https://api.iconify.design/oi-magnifying-glass.svg') no-repeat left center / contain;
  padding-left: 20px;

}
<input type="text" placeholder="Searchin..." name="s" />

And since it appears you are already using bootstrap, here is that technique for version 3.3.7, but similar in 4.x using your SVG:

#demos-search-icon {
  width: 14px;
  height: 14px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap-theme.css" rel="stylesheet" />

<div class="input-group">
  <label class="input-group-addon" for="exampleInputAmount">
    <svg version="1.1" id="demos-search-icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
      <style type="text/css">
        .st0{fill:#3F3F3F;}
      </style>
      <path class="st0" d="M8,1c3.31,0,6,2.69,6,6c0,1.55-0.59,2.96-1.56,4.03l2.27,2.27c0.39,0.39,0.39,1.02,0,1.41
        C14.51,14.9,14.26,15,14,15s-0.51-0.1-0.71-0.29l-2.43-2.43C10.01,12.74,9.04,13,8,13c-3.31,0-6-2.69-6-6S4.69,1,8,1z M8,11
        c2.21,0,4-1.79,4-4c0-2.21-1.79-4-4-4S4,4.79,4,7C4,9.21,5.79,11,8,11z"/>
    </svg>      
  </label>
  <input type="text" class="form-control" id="exampleInputAmount" placeholder="Searchin...">
</div>

Or using the stock graphics in bootstrap 3.3.7 (https://www.glyphicons.com/):

<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet" />

<div class="input-group">
  <label class="input-group-addon" for="exampleInputAmount">
    <span class="glyphicon glyphicon-search"></span>
  </label>
  <input type="text" class="form-control" id="exampleInputAmount" placeholder="Searchin...">
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

Much cleaner, much better.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.