Put icon inside input element in a form
Asked Answered
C

22

382

How do I put an icon inside a form's input element?

Screenshot of a web form with three inputs which have icons in them

Live version at: Tidal Force theme

Colchis answered 27/5, 2009 at 19:36 Comment(3)
This works. https://mcmap.net/q/88171/-39-x-39-not-displaying-in-firefox-inputs-when-using-type-quot-search-quot-with-custom-cssWeintraub
Does this answer your question?: geeksforgeeks.org/…Vela
Link is so dead.Steeple
O
500

The site you linked uses a combination of CSS tricks to pull this off. First, it uses a background-image for the <input> element. Then, in order to push the cursor over, it uses padding-left.

In other words, they have these two CSS rules:

background: url(images/comment-author.gif) no-repeat scroll 7px 7px;
padding-left:30px;
Owensby answered 27/5, 2009 at 19:42 Comment(9)
Could you please describe more about top and left parameters (7px 7 px) and other attributes? That is must be helpful.Cloverleaf
the padding-left is being ignored by Internet Explorer 8. Well not really ignored, but as soon as I type a long input, the input begins to appear in front of the icon.Fir
Advice: stop using and supporting IE 8.Elata
how can I align the image to the right end of the input field?Ossified
The problem with background images is that Chrome's autofill removes the background image and makes the background yellow completelyFredenburg
To align to the right use: background-position: right;Lachman
to add it on the right with some space background-position: center; background-position-x: calc(100% - 12px);Nikolaos
to align it to the center use: background-position-y: center;Nevil
align to the right: background: url("/search.svg") no-repeat 94% center;Basting
I
80

A solution without background-images:

.icon {
  padding-left: 25px;
  background: url("https://static.thenounproject.com/png/101791-200.png") no-repeat left;
  background-size: 20px;
}
<input type="text" class="icon" value placeholder="Search">

Or for right to left icon

.icon-rtl {
  padding-right: 25px;
  background: url("https://static.thenounproject.com/png/101791-200.png") no-repeat right;
  background-size: 20px;
}
<input type="text" class="icon-rtl" value placeholder="Search">
Intro answered 26/10, 2016 at 11:30 Comment(4)
A minor issue with this - the image is positioned over (z axis) the input, so it blocks clicks over it from focusing on the input (this can be observed in the snippet). It's possible to resolve by sending the image under the inputTheoretical
how about color, if I wish to add color as well along with icon ?Salisbarry
I like this solution but how to use a different icons? I have to pay to thenounproject.com to get an icon? and what if the company is out of business will my link to that icon dissappear?Offbeat
You can use any other photo, just put the photo file next to your file and put its address in front of background: For example background: url ("iconName.png")Intro
I
78

The CSS solutions posted by others are the best way to accomplish this.

If that should give you any problems (read Internet Explorer 6), you can also use a borderless input inside of a div.

<div style="border: 1px solid #DDD;">
    <img src="icon.png"/>
    <input style="border: none;"/>
</div>

It is not as "clean", but it should work on older browsers.

Indeterminism answered 27/5, 2009 at 19:48 Comment(6)
a good addition to this answer. sometimes ie gives problems and this is a good way to solve one of them. worked for me albeit with a span instead.Introrse
Nice way to add more complex structures inside inputs!Copyholder
@jonhue, I wouldn't recommend this unless you're still living in the previous decade and need to support IE6. Even then, I wouldn't call it "clean."Indeterminism
@Indeterminism How would you include links inside inputs then?Copyholder
Idk about this, if you click on the image, would it select/highlight/focus the input field?Watthour
very handy and easy to be understoodColchicine
S
40

You can try this:

input[type='text'] {
    background-image: url(images/comment-author.gif);
    background-position: 7px 7px;
    background-repeat: no-repeat;
}
Strutting answered 27/5, 2009 at 19:43 Comment(0)
Y
38

I find this to be the best and cleanest solution. Using text-indent on the input element:

#icon {
  background-image: url(../images/icons/dollar.png);
  background-repeat: no-repeat;
  background-position: 2px 3px;
}
<input id="icon" style="text-indent:17px;" type="text" placeholder="Username" />
Yesseniayester answered 2/9, 2015 at 10:20 Comment(4)
I'm supporting text-indent because padding-left will increase field's width and it'll overflow out of the parent element.Nichollenicholls
why did you put the style inline instead of in the #icon css?Helenhelena
@WylliamJudd That is just for demonstration purpose :)Yesseniayester
why did you use id instead of class?Intro
W
27

A simple and easy way to position an icon inside of an input is to use the position CSS property as shown in the code below. Note: I have simplified the code for clarity purposes.

  1. Create the container surrounding the input and icon.
  2. Set the container position as relative
  3. Set the icon as position absolute. This will position the icon relative to the surrounding container.
  4. Use either top, left, bottom, right to position the icon in the container.
  5. Set the padding inside the input so the text does not overlap the icon.

#input-container {
  position: relative;
}

#input-container > img {
  position: absolute;
  top: 12px;
  left: 15px;
}

#input-container > input {
  padding-left: 40px;
}
<div id="input-container">
  <img/>
  <input/>
</div>
Watersick answered 3/9, 2019 at 4:0 Comment(3)
Clean and simple, yes. You should also remove the input border with input { border: none; } and add the border to #input-container { border: 1px solid #000; } to make it look like the image is inside and actually part of the input.Rhizocarpous
@MarioWerner he pushed the image inside the input, no need to do border hacks, that's the beauty. I am going to use the idea.Neogothic
This is an excellent comprehensive answer! saved me much time thank you for thisSnakebird
S
9

This works for me:

input.valid {
   border-color: #28a745;
   padding-right: 30px;
   background-image: url('https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR2-0-tdMgUcj4LMrtAfUkfQfYhAXgBqn2OjjYgjVUJoMQOy99BjIbzqEYyd0x32xpBDEY&usqp=CAU');
   background-repeat: no-repeat;
   background-size: 20px 20px;
   background-position: right center;
}
<form>
<label for="name">Name</label>
<input class="valid" type="text" name="name" />
</form>
Servo answered 3/9, 2018 at 22:3 Comment(4)
the image disappear when autocompleting on chromeDidst
How do you make the image clickable, e.g. if using a "save" icon?Bede
It worked for me for my hybrid app, I just made the whole input box clickable after inserting image.Frictional
can I use your code both for personal and commercial projects ?Neutralization
A
8

Use:

.icon{
    background: url(1.jpg) no-repeat;
    padding-left: 25px;
}

Add the above tags into your CSS file and use the specified class.

Arlindaarline answered 28/5, 2014 at 10:4 Comment(0)
O
8

Use this CSS class for your input at the start, and then customize accordingly:

.inp-icon {
    background: url(https://i.imgur.com/kSROoEB.png)no-repeat 100%;
    background-size: 16px;
}
<input class="inp-icon" type="text">
Optometry answered 13/2, 2019 at 6:48 Comment(1)
do you know how to set click event only for this image.?Calorie
B
8

I achieved this with the code below.

First, you flex the container which makes the input and the icon be on the same line. Aligning items makes them be on the same level.

Then, make the input take up 100% of the width regardless. Give the icon absolute positioning which allows it to overlap with the input.

Then add right padding to the input so the text typed in doesn't get to the icon. And finally use the right CSS property to give the icon some space from the edge of the input.

Note: The Icon tag could be a real icon if you are working with ReactJs or a placeholder for any other way you work with icons in your project.

.inputContainer {
  display: flex;
  align-items: center;
  position: relative;
}

.input {
  width: 100%;
  padding-right: 40px;
}

.inputIcon {
  position: absolute;
  right: 10px;
}
<div class="inputContainer">
   <input class="input" />
   <Icon class="inputIcon" />
 </div>
Barmecidal answered 8/10, 2020 at 20:15 Comment(0)
S
6

You can try this: Bootstrap-4 Beta

https://www.codeply.com/go/W25zyByhec

<div class="container">
    <form>
        <div class="row">
            <div class="input-group mb-3 col-sm-6">
                <input type="text" class="form-control border-right-0" placeholder="Username" aria-label="Username" aria-describedby="basic-addon1">
                <div class="input-group-prepend bg-white">
                    <span class="input-group-text border-left-0 rounded-right bg-white" id="basic-addon1"><i class="fas fa-search"></i></span>
                </div>
            </div>
        </div>
    </form>
</div>
Surfacetoair answered 23/6, 2018 at 4:6 Comment(0)
J
4

Just use the background property in your CSS.

<input id="foo" type="text" />
#foo
{
    background: url(/img/foo.png);
}
Josi answered 27/5, 2009 at 19:42 Comment(0)
S
4

I had situation like this. It didn't work because of background: #ebebeb;. I wanted to put background on the input field and that property was constantly showing up on the top of the background image, and i couldn't see the image! So, I moved the background property to be above the background-image property and it worked.

input[type='text'] {
    border: 0;
    background-image: url('../img/search.png');
    background-position: 9px 20px;
    background-repeat: no-repeat;
    text-align: center;
    padding: 14px;
    background: #ebebeb;
}

Solution for my case was:

input[type='text'] {
    border: 0;
    background: #ebebeb;
    background-image: url('../img/search.png');
    background-position: 9px 20px;
    background-repeat: no-repeat;
    text-align: center;
    padding: 14px;
}

Just to mention, border, padding and text-align properties are not important for the solution. I just replicated my original code.

Sazerac answered 10/5, 2018 at 19:24 Comment(3)
This is super old and I hope maybe you've learned since over a year ago, but background is a shorthand property name which you use to cover all the background properties at once: background: [color] [image url] [repeat] [position], and that's why your color was overwriting everything. You could also have left it in place and renamed the property to background-colorFantail
@Fantail yes you are right. it's almost always best to use shorthand property name, totally agree on that. But purpose of this post is to point out that order of properties sometimes matters, and those 'small' CSS rules can be frustrating a lot, especially to newcomers in development.Sazerac
Totally agree, but the point still stands: background is a shorthand property name. A better fix would have been to not use the shorthand, but use background-color for the color property (assuming you want both a color and an image).Fantail
R
3

I was able to add an icon to an input field by adding the icon as a background image through CSS. From there, you can adjust the size of the image using the background-size property and finally, position the element with the background-position-x and background-position-y properties. I've shared a code snippet below and linked to a working example in Codepen here:

body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}

.input-container {
  padding: 50px;
}

input {
  box-sizing: border-box;
  width: 250px;
  padding-left: 36px;
  height: 48px;
  background-image: url('https://image.shutterstock.com/image-vector/apple-icon-vector-fruit-symbol-260nw-1466147615.jpg');
  background-size: 20px;
  background-position-x: 10px;
  background-position-y: 50%;
  background-repeat: no-repeat;
  border-radius: 15px;
}
<!DOCTYPE>
<html>

<head>
  <title>Icon Inside Input Field</title>
</head>

<body>

  <div class="input-container">
    <label for="email"><p>Email:</p></label>
    <input type="text" name="email" id="email" placeholder="[email protected]">
  </div>

</body>

</html>

https://codepen.io/Iram_Tech/pen/GRQqrNg

Rohde answered 11/5, 2022 at 1:31 Comment(0)
I
2

Using with font-icon

<input name="foo" type="text" placeholder="&#61447;">

OR

<input id="foo" type="text" />

#foo::before
{
  font-family: 'FontAwesome';
  color:red;
  position: relative;
  left: -5px;
  content: "\f007";    
}
Imperishable answered 6/1, 2017 at 19:36 Comment(2)
Seems that ::before can not be applied of input element.Lani
seems this css works only on non-input element, like div.Ichthyoid
C
1
 <label for="fileEdit">
    <i class="fa fa-cloud-upload">
    </i>
    <input id="fileEdit" class="hidden" type="file" name="addImg" ng-file-change="onImageChange( $files )" ng-multiple="false" accept="{{ contentType }}"/>
  </label>

For example you can use this : label with hidden input (icon is present).

Coreen answered 9/12, 2015 at 15:41 Comment(2)
Good solution, but please add an explanation for your solution.Duckling
I don't remember it now =) I've lost UI experience ... 2015...backend only..)Coreen
L
1

I didn't want to change the background of my input text neither. It will work with my SVG icon.

I added a negative margin to the icon, so it appeared inside the input box.

And adding the same value padding to the input, so the text wouldn't go under the icon.

<div class="search-input-container">

  <input
    type="text"
    class="search-input"
    style="padding-right : 30px;"
  />

  <img
    src="@/assets/search-icon.svg"
    style="margin-left: -30px;"
   />

</div>

The inline-style is for readability. Consider using classes.

Labbe answered 1/9, 2020 at 22:37 Comment(0)
T
0

You could go for a different approach which also allows you to click it and have it do a function. Have a look at the example below:

<div id="search-bar">
  <input placeholder="Search or Type a URL">
  <button><i class="fas fa-search"></i></button>
</div>
#search-bar {
  display: flex;
  justify-content: center;
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  height: 60px;
}
#search-bar > input {
  width: 750px;
  font-size: 30px;
  padding: 20px;
  border-radius: 50px 0px 0 50px;
  border: none;
  border-top: 1px solid #000;
  border-bottom: 1px solid #000;
  border-left: 1px solid #000;
  background: #FFF; /* CSS Edit Here */
}
#search-bar > button {
  background: #FFF;
  border: none;
  font-size: 30px;
  border-right: 1px solid #000;
  border-top: 1px solid #000;
  border-bottom: 1px solid #000;
  border-radius: 0 50px 50px 0 ;
  padding-right: 20px;
}
Tedford answered 20/7, 2021 at 16:11 Comment(0)
M
0

The CSS background solutions do it for most cases, but it has a problem with WebKit (chrome) autocomplete where the icon disappear.

There are other solutions that includes changing the HTML/DOM structure by wrapping the input in a div and adding an extra element (img, div, or similar).

I don't like does solutions because you need to tweak the elements CSS with absolute positions and/or resizing by pixel to get the right place. Or recreate the input border to "merge" input and img in one.

So this solution is based on a CSS background image not applied over the input element, but applied over a wrapper div.

HTML:

<div class="input-email">
    <input type="text" placeholder="Email" name="email" id="email">
</div>

CSS:

.input-email {
    background: url(/assets/images/email.svg) no-repeat scroll 14px 11px;
    display: inline-block;
}

.input-email input{
    padding-left: 40px;
    background-color: transparent !important;
}

input:-webkit-autofill, input:-webkit-autofill:hover,
input:-webkit-autofill:focus, input:-webkit-autofill:active {
    transition: background-color 5000s ease-in-out 0s;
}
  1. This way with .input-email class I define my icon image as div background (not affected by WebKit autocomplete background).
  2. Next .input-email input definition I pad left the input element to give space for the image and set it as transparent (this works when autocomplete is not applied)
  3. Finally with webkit-autofill classes I remove with transition the background-color set by the autocomplete.

Note: at point 2 I set transparent !important because this -internal-autofill-selected gets rendered at browser and I couldn't overwrite it without setting my also as !important:

input:-internal-autofill-selected {
    background-color: -internal-light-dark(rgb(232, 240, 254), rgba(70, 90, 126, 0.4)) !important;
}

I got my solution from this post https://www.py4u.net/discuss/1069380. I have make some tweaks, though major credits are to them.

Millman answered 14/1, 2022 at 17:42 Comment(0)
K
0

In case, if you have <i class=''></i> with imported fonts, background: ... (some png) implementation will not be suited for you.

So try this one:

<div class="parent">
   <form action='' method='post'>
      <i class="fa-solid fa-paperclip"></i>
      <input type="text" name="message" placeholder="Type...">            
   </form>
</div>
.parent > form > i {
   position: absolute;
}

.parent > form > input {
   text-indent: 40px
}

then, use margin to set Icon inside and text-indent to move placeholder's text.

...

...

Here is full example of my code

.parent {
   width: 100%;
   height: 70px;
   display: flex;
   flex-direction: column;
   justify-content: center;
}

.parent > form > i {
    margin-left: 24px;
    margin-top: 13px;
    position: absolute;
}

.parent > form > input {
    width: 70%;
    height: 40px;
    margin-left: 8px;
    text-indent: 40px;
}
Kelvin answered 24/2, 2023 at 15:3 Comment(1)
text-indent is a critical thing in terms of usability.Oblate
A
-1

.input_container {
  display: flex;
  border-bottom: solid 1px grey;
  transition: border-color 0.1s ease-in;
  background: white;
}

.input {
  color: blue;
  display: block;
  width: calc(100% - 20px);
  border: none;
  outline: none;
  padding: 8px 16px;
}

.input_img {
  flex-basis: 20px;
  display: inline-block;
  padding: 8px 16px;
  cursor: pointer;
}
<div class="input_container">
  <input type="text" class="input" value>
  <span class="input_img" data-role="toggle">
    <svg
      width="24"
      height="24"
      viewBox="0 0 24 24"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
        <path
          d="M8 9C7.44772 9 7 9.44771 7 10C7 10.5523 7.44772 11 8 11H16C16.5523 11 17 10.5523 17 10C17 9.44771 16.5523 9 16 9H8Z"
          fill="currentColor"
        />
        <path
          fill-rule="evenodd"
          clip-rule="evenodd"
          d="M6 3C4.34315 3 3 4.34315 3 6V18C3 19.6569 4.34315 21 6 21H18C19.6569 21 21 19.6569 21 18V6C21 4.34315 19.6569 3 18 3H6ZM5 18V7H19V18C19 18.5523 18.5523 19 18 19H6C5.44772 19 5 18.5523 5 18Z"
          fill="currentColor"
        />
      </svg>
    </span>
</div>
Antalya answered 8/4, 2021 at 8:43 Comment(4)
Good solution, but please add an explanation for your solution.Duckling
Not a good solution in my opinion as we have to add extra span and img tag to accomplish the same objective that can. be achieved by simple css.Izy
@JunaidNazir you are quick to conclude it is not a good solution because of your reason that it involves extra span and img. An img is not even involved and a using a span doesn't hurt. Besides, you can customise it however you choose, I have only provided one way of achieving the desired behaviour/look.Antalya
@Antalya You are absolutely right that is why I wrote in my opinion. Totally agreed with you & solution works as well.Izy
S
-4

This works for me for more or less standard forms:

  <button type="submit" value="Submit" name="ButtonType" id="whateveristheId" class="button-class">Submit<img src="/img/selectedImage.png" alt=""></button>
Skippy answered 29/4, 2020 at 13:4 Comment(1)
Not buttons, inputs.Duckling

© 2022 - 2024 — McMap. All rights reserved.