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.
Related
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;
}
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;
}
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;
}
I'm trying to achieve this layout:
I have this:
<div class="button-wrapper">
<button>
<i></i>
</button>
<label>Carregamento Telemóvel</label>
</div>
My label has to be absolute positioned because it can't take space in the div. The div has to be the width of the button.
Any ideas?
EDIT: Sorry guys, my question was done in a little bit of hurry, so it was incomplete. I will now explain detailed.
I need all the div's to be responsive and don't have a fixed width.
The button itself it's contained in a row with others button's with the same layout.
The button's have to have the same margin between them, that's why I can't have the label with with because the length of the text it's never the same so the div's will have different sizes, and then I can't give the same margin between them.
Solution:
http://plnkr.co/edit/NYOb3uQnYrNFkfO6RaIG?p=preview
The plunker just works in -webkit- but it's all I need.
The trick to centering the label is a CSS3 transform
.button-wrapper label {
position: absolute;
top:100%;
left: 50%;
transform:translateX(-50%);
color: orange;
font-weight: bold;
}
body {
text-align: center;
}
.button-wrapper {
display: inline-block;
margin: 1em;
position: relative;
}
.button-wrapper i {
font-size: 72px;
background: orange;
line-height: 1.4em;
width: 1.4em;
border-radius:50%;
display: block;
}
.button-wrapper label {
position: absolute;
top:100%;
left: 50%;
transform:translateX(-50%);
color: orange;
font-weight: bold;
}
<div class="button-wrapper">
<i>K</i>
<label>Carregamento Telemóvel</label>
</div>
.button-wrapper {
display: inline-block;
max-width: 80px;
text-align: center;
}
.button-wrapper > button {
border-radius: 50%;
height: 40px; width: 40px;
background-color: orange;
position: relative;
border: 0 none;
display: inline-block;
}
.button-wrapper > button > i {
display: block;
height: 10px;
width: 10px;
background-color: #ffffff;
margin-top: -5px;
margin-left: -5px;
left: 50%;
top: 50%;
position: absolute;
}
.button-wrapper > label {
display: block;
font-size: 11px;
color: orange;
}
<div class="button-wrapper">
<button>
<i></i>
</button>
<label>Carregamento Telemóvel</label>
</div>
Without seeing your code, it's difficult to help you. But you can center an absolute positioned block element by combining margin:0 auto; left:0; right:0;
JSFiddle - http://jsfiddle.net/vfs3n68e/
Here's a very simple way to do it that I've created quickly: https://jsfiddle.net/rn8ysg5q/
HTML:
<div class="button-wrapper">
<button>
<i></i>
</button>
<br />
<label>Carregamento Telemóvel</label>
</div>
CSS:
.button-wrapper
{
/*border: 1px dotted red;*/
color: orange;
width: 100px;
position: relative;
text-align: center;
}
/* Reset button layout */
.button-wrapper button
{
background: none;
border: 0;
color: inherit;
/* cursor: default; */
font: inherit;
line-height: normal;
overflow: visible;
padding: 0;
-webkit-appearance: button; /* for input */
-webkit-user-select: none; /* for button */
-moz-user-select: none;
-ms-user-select: none;
}
.button-wrapper button
{
width: 60px;
height: 60px;
background-color: orange;
border-radius: 50%;
}
If that's what you're looking for I'll update it once I'm home in an hour and make some improvements.
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