Add icon via :before to <input> element - html

I've got an <input>-element. I'd like to precede it with a search-icon using the :before selector including a SVG-font I created.
.icon-search:before {
content: "\f109";
text-indent: -2em;
}
My problem is that the pseudo-selector :beforedoesn't seem to work with <input> Can you tell me how to make this work in the most elegant way?
This is how I want it to look once I'm done.

The before/after pseudo element is contained inside the element but input can't have that, so you have to use another selector like span or div. This is an implementation similar to what bootstrap does...
FIDDLE
HTML:
<div class="wrapper">
<div class="inputgroup"> <span class="innericon searchicon"></span>
<input type="text" class="search" placeholder="search..." />
</div>
</div>
CSS:
body {
color: gray;
}
.wrapper {
margin: 20px auto;
width: 40%;
}
* {
box-sizing: border-box;
}
.inputgroup {
position:relative;
display: inline-block;
height: 30px;
line-height: 30px;
vertical-align: middle;
}
.search {
border-radius: 8px;
height: 30px;
line-height: 30px;
padding: 3px 6px 3px 32px;
border: none;
font-size: 13px;
display: inline-block;
vertical-align: middle;
border: 1px solid #CCC;
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.075) inset;
}
.inputgroup .innericon {
position: absolute;
top: 4px;
left: 8px;
z-index: 2;
display: block;
text-align: center;
pointer-events: none;
}
.searchicon:before {
content: "\f109";
}

Here is one way to achieve this: http://jsfiddle.net/n9gjb3kr/
You need to put your input inside a div:
<div class="icon-search"><input type="text"></input></div>
.icon-search:before {
content: "\f109";
position: absolute;
left: 0;
top: 0;
height: 24px;
width: 24px;
margin-left: .5em;
width: 0;
overflow: visible;
display: inline-block;
line-height: 24px;
z-index: 1;
}
.icon-search {
position: relative;
line-height: 24px;
}
.icon-search > input {
border-radius: 12px;
height: 24px;
border: 1px solid black;
margin: 0;
padding: 0;
padding-left: 32px;
}

You can wrap the input into span, setting the span with position:relative and
then add to input and icon position:absolute and play with margins and z-index to create the same effect. This is pretty solid for responsive as well, if you style the span and the input the right way taking the responsive design in account.
OR
Using jquery as already mentioned in the comments

Related

Hover on child without changing parent

Hover on child element <button> without hover effect on parent <h2>
.parent {
display: block;
text-align: center;
font-weight: 700;
font-size: 31px;
letter-spacing: normal;
position: relative;
}
.parent:hover {
color: orange;
}
span {
line-height: unset;
vertical-align: baseline;
top: 0;
left: 0;
position: absolute;
color: transparent;
box-shadow: none;
z-index: 5;
}
span button {
position: absolute;
left: 0;
top: -20px;
color: #fff;
width: 30px;
height: 30px;
min-width: 30px;
min-height: 30px;
z-index: 5;
background: #0085ba !important;
border-radius: 50%;
border: 2px solid #fff;
box-sizing: border-box;
padding: 3px;
display: inline-block;
overflow: hidden;
}
<h2 class="parent">
Title
<span class="child">
<button>+</button>
</span>
</h2>
This can be helpful
example
.html
<div class="parent1">
<div class="child1">
/*.....*/
.css
.parent1:hover{
cursor: pointer;
}
.parent1:hover .child1{
/*......*/
}
snippet
.parent:hover .child {
/* ... */
}
Add the below:
parent:hover {
cursor:pointer
}
It's a little tricky.
First you need to get the parent from the child :
const _parent = document.querySelector('selectorOfParentFromChild')
After you have to add the class on child and remove on parent. You need to do it one child event : 'onMouseOver'.
SO:
[child, parent].forEach(node=>node.addEvenListener('onmouseover', (event)=>{
event.stopPropagation();
const _parent = document.querySelector('selectorOfParentFromChild')
node.classlist.add(wanted)
_parent.classlist.remove(wanted)
})
This has been asked before, and answers seem to come within the span of: "css can't do that", "you should probably restructure your divs" and "here's a trick".
hover on child without hover effect on parent
Now I don't have the experience to say if a structure that neccesitates this is actually bad, but in either case, there is now a straight-forward solution with :has()
.parent {
display: block;
text-align: center;
font-weight: 700;
font-size: 31px;
letter-spacing: normal;
position: relative;
}
.parent:not(:has(.child:hover)):hover {
color: orange;
}
span {
line-height: unset;
vertical-align: baseline;
top: 0;
left: 0;
position: absolute;
color: transparent;
box-shadow: none;
z-index: 5;
}
span button {
position: absolute;
left: 0;
top: -20px;
color: #fff;
width: 30px;
height: 30px;
min-width: 30px;
min-height: 30px;
z-index: 5;
background: #0085ba !important;
border-radius: 50%;
border: 2px solid #fff;
box-sizing: border-box;
padding: 3px;
display: inline-block;
overflow: hidden;
}
<h2 class="parent">
Title
<span class="child">
<button>+</button>
</span>
</h2>
This is what that selector is saying in English:
Select all elements ".parent" - except the ones who have any child elements ".child" being hovered on - when they are hovered on.
You will have to delete the CSS for parent:hover and if you only want the hover effect on the button then the parent shouldn't have a hover effect in your CSS.
.parent {
display: block;
text-align: center;
font-weight: 700;
font-size: 31px;
letter-spacing: normal;
position: relative;
}
span {
line-height: unset;
vertical-align: baseline;
top: 0;
left: 0;
position: absolute;
color: transparent;
box-shadow: none;
z-index: 5;
}
span button {
position: absolute;
left: 0;
top: -20px;
color: #fff;
width: 30px;
height: 30px;
min-width: 30px;
min-height: 30px;
z-index: 5;
background: #0085ba !important;
border-radius: 50%;
border: 2px solid #fff;
box-sizing: border-box;
padding: 3px;
display: inline-block;
overflow: hidden;
}
button:hover {
color: orange;
}

How to have a border and a bottom border on a button

I need to achieve this button.
Here is my code so far:
.button {
border-color: red;
border-radius: 8px
}
.button::after {
content: '';
background-color: red;
display: block;
width: inherit;
height: 3px;
}
<button class="button">Click me </button>
The problem is that the width covers 100% of the screen, and I need the width of the button; I can't give a specific width to this button because it will receive dynamic text.
You just need to wrap the button in a div with display: inline-block to prevent it going full-width and relative positioning so it can contain an absolutely positioned element inside and from the looks of your image some padding on that element as well to create some space between the button and the line below. Then make your :after pseudo element absolutely positioned and give it width: 100%.
div {
position: relative;
padding: .75rem .5rem;
box-sizing: border-box;
display: inline-block
}
button {
background: transparent;
border-radius: .5rem;
border: 3px solid #EF544F;
padding: .5rem;
color: #EF544F;
font-weight: 600;
font-size: 1.2rem
}
button::after {
content: '';
background-color: #EF544F;
display: block;
position: absolute;
width: inherit;
height: 4px;
width: 100%;
bottom: 0;
left: 0;
border-radius: 999px;
}
<div>
<button>Click me</button>
</div>
This seems to be like on picture:
.button
{
border-radius: 0.5em;
padding: 0.4em 0.8em 0.2em 0.8em;
color: red;
font-weight: bold;
border: 2px solid red;
background-color: transparent;
}
.button::after
{
content: '';
background-color:red;
display: block;
height: 3px;
position: relative;
left: -1.3em;
bottom: -1em;
width: calc(100% + 2.6em);
}
<button class="button">Tab Tile</button>
you can try min-width
.button::after{
content: '';
background-color:red;
display: inline-block;
width: auto;
height: 3px;
min-width:100px;
}

Creating a circle around a letter inside a H1 tag

Creating a circle around a letter or text works fine, but in my case I only want to circle a single letter within a word (which is within an H1 tag):
.large {
font-size: 5em;
}
.circle {
border-radius: 50%;
padding: -0.5% 5% 0% 5%;
background: #fff;
border: 10px solid red;
color: red;
}
<h1 class="large">
<span class="circle">e</span>Text
</h1>
Fiddle is here: https://jsfiddle.net/henzen/zwph2nsv/4/
This produces:
Notice that the circle is conforming to the H1 height (I think) - I need it to be compressed vertically, ie the vertical padding needs to be the same as the horizontal, tightly wrapped around the "e".
Is this possible, or would I need to separate the "e" from the "Text" completely in the HTML?
I have tried Unicode chars (eg, &#9428), which work, but cannot be reliably styled across browsers.
Thanks for any pointers.
You could use a pseudo element.
.large {
font-size: 5em;
}
.circle {
position: relative;
color: red;
}
.circle:after {
content: '';
width: 39px;
height: 44px;
border: 4px solid red;
position: absolute;
border-radius: 50%;
left: -5px;
top: 27px;
}
<h1 class="large">
<span class="circle">e</span>Text
</h1>
use a pseudo element.
Try This: https://jsfiddle.net/2gtazqdy/12/
* {
margin: 0;
padding: 0;
}
.large {
font-size: 5em;
}
.circle {
height: 50px;
width: 50px;
display: inline-block;
padding-left: 20px;
}
.circle::after {
display: inline-block;
height: 50px;
width: 50px;
z-index: 1;
position: absolute;
top: 18px;
left: 4px;
content: "";
color: red;
background: transparent;
border: 10px solid red;
border-radius: 50%;
}
My output:
try this
for your html do <h1> <span> C </span> ircle </h1>
then in the css define your h1 span
and give it padding, in the shape of a rectangle you could use this =
padding: 20px 10px;
then add a border, for example =
border: 5px solid #ddd;
then at last give it a border radius, this is a bit tidious to figure out but just play around with the pixels and you'll eventually get it right how you want it.
for example =
Border-radius: 20px
your html:
<h1> <span> C </span>ircle </h1>
your total css:
h1 span{
padding: 20px 10px;
border: 5px solid #ddd;
border-radius: 20px;
}
If you want to make a circle, the following is needed:
display: inline-block (or display: block)
same width, height and line-height
text-align: center
Use em to correspond with the font-size of the container.
Example
.large {
font-size: 5em;
}
.circle {
display: inline-block;
width: 0.8em;
height: 0.8em;
line-height: 0.8em;
text-align: center;
border-radius: 50%;
background: #fff;
border: 0.05em solid red;
color: red;
}
<h1 class="large">
<span class="circle">e</span>Text
</h1>
Please try this code
.large{
text-align: center;
font: 40px Arial, sans-serif;
color:#000;
font-weight:bold;
}
.circle {
border-radius: 50%;
background: #fff;
border: 6px solid red;
padding: 3px 10px;
text-align: center;
font: 28px Arial, sans-serif;
color: #000;
font-weight: bold;
}
<h1 class="large">
<span class="circle">e</span>Text
</h1>

Create Button with toggle and text with a single element

I'm trying to create a button out of a single html element. The button needs to have a toggle slider and the text needs to be aligned vertically and horizontally. So I thought I can make use of :before element to help me make that happen. Here is what I have tried:
div {
width: 140px;
height: 40px;
background-color: #B3B3B3;
color: #FFF;
float: left;
clear: both;
border-radius: 5px;
font-size: 12px;
}
div:before {
content: '';
display: block;
width: 20px;
height: 36px;
background-color: #4D4D4D;
position: relative;
left: 2px;
top: 2px;
float: left;
border-radius: 5px;
}
<div>Text Value</div>
I have 2 problems with the above code:
I can't position the text how I want and I have tried using text-align and position to move it around.
I am using a float, which means that it will affect behavior of other elements around it, and I really don't want that.
Is what I want possible with a single element?
Here is the JS Fiddle: https://jsfiddle.net/m3q5Lcjy/
EDIT: The centered text should not be centered on the whole element, but on the light gray area.
This is how I would do this:
Array.from(document.querySelectorAll('.toggler')).forEach((item) => {
item.addEventListener('click', e => {
item.classList.toggle('active');
})
});
.toggler {
display: flex;
align-items: center;
justify-content: center;
position: relative;
box-sizing: border-box;
padding-left: 24px;
width: 140px;
min-height: 40px;
background-color: #B3B3B3;
color: #FFF;
border-radius: 5px;
font-size: 12px;
text-align: center;
cursor: pointer;
transition: padding .25s ease;
}
.toggler.active {
padding: 0 24px 0 0;
}
.toggler:before {
content: '';
display: block;
width: 20px;
background-color: #4D4D4D;
position: absolute;
bottom: 2px;
left: 2px;
top: 2px;
border-radius: 5px;
/* transition to make it look smoother */
transition: left .4s ease;
z-index: 1;
}
.toggler.active:before {
left: calc(100% - 22px);
}
<div class="toggler">Text Value</div>
<hr />
<div class="toggler active">Text Value realllllyy long</div>
<hr />
<div class="toggler">Text Value really far too long for this tiny, tiny, ohhh so tiny button. I recommend using shorter text though, but it won't break not even if you have like 10 or more lines.</div>
If anything about this implementation is unclear, feel free to ask.
Use flexbox to center your text vertically and horizontally. Then use absolute positioning on your pseudo element. Make sure parent element has relative positioning applied so absolute positioned pseudo stays within the parent.
div {
display: flex;
align-items: center;
justify-content: center;
position: relative;
box-sizing: border-box;
padding-left: 24px; /* 20px for :before width, 4px for :before offset */
width: 140px;
height: 40px;
background-color: #B3B3B3;
color: #FFF;
border-radius: 5px;
font-size: 12px;
}
div:before {
content: '';
display: block;
width: 20px;
height: 36px;
background-color: #4D4D4D;
position: absolute;
left: 2px;
top: 2px;
border-radius: 5px;
}
<div>Text Value</div>
You could place the text in a paragraph.
<div class="thediv">
<p class="theText">
enter text here
</p>
</div>
.thediv{
Your own style.
}
.theText{
position: absolute;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
}
I don't see why you would want it be in one element.
If you do want that, you should give the div a padding.
div{
background-color: #B3B3B3;
color: #FFF;
float: left;
border-radius: 5px;
font-size: 12px;
padding: 20px 70px;
}

How can I float dynamic div's next to each other?

I'm creating my own version of Twitter Bootstrap radio buttons purely based on CSS. The visual feedback for selected radio button is based on input[type="radio"]:checked + span.
As the content of my "buttons" can vary, the width is dynamic. This causes problem aligning the button next to each other.
In my JSfiddle I've set fixed width of 50px. Removing this and the buttons are on top of each other.
Can anyone point me in the right direction of how I can accomplish this?
Here is my code:
//HTML
<div class="button-group binary" data-toggle="buttons-radio">
<div class="radio-wrapper">
<input type="radio" class="active" name="status" value="1" />
<span class="background">Yes</span>
</div>
<div class="radio-wrapper">
<input type="radio" class="inactive" name="status" value="0" checked="checked" />
<span class="background">No</span>
</div>
</div>
//CSS
.button-group{
/*display: table;*/
display: block;
}
.radio-wrapper {
/*display: table-cell; */
display: inline-block;
position: relative;
height: 28px;
margin: 0;
width: 50px; /* I want this to be dynamic */
}
.radio-wrapper:first-child .background{
border-right: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.radio-wrapper:last-child .background{
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
input[type="radio"]{
position: absolute;
display: block;
height: 28px;
width: 100%;
z-index: 200;
cursor: pointer;
opacity: 0;
}
input[type="radio"]:checked + span {
background-color: #63B1DE;
color: #fff;
}
.background {
position: absolute;
z-index: 100;
height: 100%;
padding: 0 5px;
border: solid 1px #87A2B2;
background-color: #fff;
text-align: center;
line-height: 28px;
text-transform: uppercase;
}
If you remove position: absolute from you background class, you will no longer need the width style:
jsFiddle
.button-group{
/*display: table;*/
display: block;
}
.radio-wrapper {
/*display: table-cell; */
display: inline-block;
position: relative;
height: 28px;
margin: 0;
/*width: 50px; not needed*/
}
.radio-wrapper:first-child .background{
border-right: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.radio-wrapper:last-child .background{
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
input[type="radio"]{
position: absolute;
display: block;
height: 28px;
width: 100%;
z-index: 200;
cursor: pointer;
opacity: 0;
}
input[type="radio"]:checked + span {
background-color: #63B1DE;
color: #fff;
}
.background {
z-index: 100;
height: 100%;
padding: 0 5px;
border: solid 1px #87A2B2;
background-color: #fff;
text-align: center;
line-height: 28px;
text-transform: uppercase;
}
Having a look at your CSS, I think the issue you are having is because you are making the .background position: absolute it is not taking up any space in its parent, so the parent doesn't really have any width, this is why you have to manually set it. Stripping out the absolute positioning for the .background and actually making it an element that takes up space will give the parent a width (which will be based on its content). Now as far as correcting the on top of each other issue, I would think some floating here would work. CSS is here (I also removed some unnecessary rules)
.radio-wrapper {
position: relative;
float:left;
}
.radio-wrapper:first-child .background{
border-right: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.radio-wrapper:last-child .background{
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
input[type="radio"]{
position: absolute;
display: block;
height: 28px;
width: 100%;
z-index: 200;
cursor: pointer;
opacity: 0;
}
input[type="radio"]:checked + span {
background-color: #63B1DE;
color: #fff;
}
.background {
height: 100%;
padding: .5em;
border: solid 1px #87A2B2;
background-color: #fff;
text-align: center;
line-height: 28px;
text-transform: uppercase;
}
As per example fiddle.
I did add a bit more padding that you had though so please feel free to adjust as required. I also like padding in ems so if your font changes in size the padding is always relative.