Custom select box - html

I am trying to style a select drop down box. The custom select box has rounded corners and a dropdown list (a box that drops down with the options) that shows on focus. I used the css below to style the select box. I have also substituted the html select with DIV elements.
Here is the code I have used so far:
document.querySelector('.custom-select-wrapper').addEventListener('click', function() {
this.querySelector('.custom-select').classList.toggle('open');
for (const option of document.querySelectorAll(".custom-option")) {
option.addEventListener('click', function() {
if (!this.classList.contains('selected')) {
this.parentNode.querySelector('.custom-option.selected').classList.remove('selected');
this.classList.add('selected');
this.closest('.custom-select').querySelector('.custom-select__trigger span').textContent = this.textContent;
}
})
}
})
.custom-select-wrapper {
position: relative;
user-select: none;
width: 188px;
z-index: 30000000000;
}
.custom-select {
position: relative;
display: flex;
flex-direction: column;
}
.custom-select__trigger {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
height: 27px;
background: #ffffff;
cursor: pointer;
border: 1px solid #707070;
border-radius: 8px;
}
.custom-options {
position: absolute;
display: block;
top: 100%;
left: 0;
right: 0;
border: 1px solid #707070;
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
background: #fff;
transition: all 0.5s;
opacity: 0;
visibility: hidden;
pointer-events: none;
z-index: 2;
}
.custom-select.open .custom-options {
opacity: 1;
visibility: visible;
pointer-events: all;
}
.custom-option {
position: relative;
display: block;
padding: 0 10px 0 10px;
line-height: 25px;
cursor: pointer;
transition: all 0.5s;
}
.arrow {
position: relative;
top: 15px;
right: 15px;
}
.arrow::before,
.arrow::after {
content: "\f0d7";
font-family: "Font Awesome 5 Free";
font-size: 20px;
font-weight: 700;
color: #394a6d;
position: absolute;
bottom: 0px;
}
<div class="custom-select-wrapper">
<div class="custom-select">
<div class="custom-select__trigger">
<span>Option 1</span>
<div class="arrow"></div>
</div>
<div class="custom-options">
<span class="custom-option selected" data-value="tesla">Option 2</span>
<span class="custom-option" data-value="volvo">Option 3</span>
</div>
</div>
</div>
The styles I have applied to the select tag are coming into effect, but the problem is that the dropdown box top border does not blend with the select box itself on focus. Is it only possible to change the SELECT input style on focus from a round border to a square border?
Would someone with some more knowledge in this regard please take a few minutes to suggest a solution?

It depends on what you mean by "blending", but if you want to achieve a more harmonious look, you can do the following:
Set the border-bottom-left-radius and border-bottom-right-radius of the trigger element to 0px when the dropdown is open, so that the select trigger visually continues to the dropdown that is visible
Remove the top border of the dropdown, so that you don't have a doubly-thick border separating the trigger and the dropdown
See proof-of-concept below:
document.querySelector('.custom-select-wrapper').addEventListener('click', function() {
this.querySelector('.custom-select').classList.toggle('open');
for (const option of document.querySelectorAll(".custom-option")) {
option.addEventListener('click', function() {
if (!this.classList.contains('selected')) {
this.parentNode.querySelector('.custom-option.selected').classList.remove('selected');
this.classList.add('selected');
this.closest('.custom-select').querySelector('.custom-select__trigger span').textContent = this.textContent;
}
})
}
})
.custom-select-wrapper {
position: relative;
user-select: none;
width: 188px;
z-index: 30000000000;
}
.custom-select {
position: relative;
display: flex;
flex-direction: column;
}
.custom-select__trigger {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
height: 27px;
background: #ffffff;
cursor: pointer;
border: 1px solid #707070;
border-radius: 8px;
transition: all 0.5s;
}
.custom-options {
position: absolute;
display: block;
top: 100%;
left: 0;
right: 0;
border: 1px solid #707070;
border-top: none;
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
background: #fff;
transition: all 0.5s;
opacity: 0;
visibility: hidden;
pointer-events: none;
z-index: 2;
}
.custom-select.open .custom-select__trigger {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.custom-select.open .custom-options {
opacity: 1;
visibility: visible;
pointer-events: all;
}
.custom-option {
position: relative;
display: block;
padding: 0 10px 0 10px;
line-height: 25px;
cursor: pointer;
transition: all 0.5s;
}
.arrow {
position: relative;
top: 15px;
right: 15px;
}
.arrow::before,
.arrow::after {
content: "\f0d7";
font-family: "Font Awesome 5 Free";
font-size: 20px;
font-weight: 700;
color: #394a6d;
position: absolute;
bottom: 0px;
}
<div class="custom-select-wrapper">
<div class="custom-select">
<div class="custom-select__trigger">
<span>Option 1</span>
<div class="arrow"></div>
</div>
<div class="custom-options">
<span class="custom-option selected" data-value="tesla">Option 2</span>
<span class="custom-option" data-value="volvo">Option 3</span>
</div>
</div>
</div>

The above code is a solution strictly from a styling point of view. But as per #CBroe remarks, from a usability point of view (for example using the select via keyboard is impossible), the code is not optimal.
This is why I came up with a solution that uses the jQuery plugin Select2
If anyone is interested here is a link to the code
https://www.codeply.com/p/Z999PpuSOK

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;
}

Event on input within div acting differently to event on input within a label

This is an odd one but I'm sure there's a simple explanation. Can someone explain to me why an event on an input within a div acts differently to an event on input within a label. Please see the following fiddle as an example:
https://jsfiddle.net/anthill/h8v106o7
$('#container .switch input[type="checkbox"]').change(function(e) {
alert($(this).data('message'));
})
body {
font-family: Helvetica, Arial, sans-serif;
padding: 10px;
}
h5 {
margin-bottom: 0.5em;
}
.switch {
background-color: #fff;
border: 1px solid #999;
border-radius: 2px;
color: #fff;
cursor: pointer;
display: inline-block;
font-size: 0;
height: 34px;
overflow: hidden;
margin: 0;
padding: 0;
position: relative;
width: 80px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
}
.switch:after, .switch:before {
background-color: #9bca3e;
color: #fff;
content: "On";
display: block;
font-size: 13px;
line-height: 1.5;
height: 100%;
left: 0;
padding: 7px 0;
position: absolute;
text-align: center;
top: 0;
width: 51%;
/* This is so the darker color doesn't show through the rounded corners of the knob */
}
.switch:before {
background-color: #999;
content: "Off";
left: auto;
right: 0;
width: 50%;
}
.switch .knob {
background: #f7f7f7;
border: 1px solid #999;
border-bottom: none;
border-top: none;
border-radius: 2px;
display: block;
font-size: 13px;
height: 100%;
left: -1px;
position: relative;
top: 0;
width: 40px;
z-index: 2;
-webkit-transition: all 0.15s ease;
-moz-transition: all 0.15s ease;
-ms-transition: all 0.15s ease;
transition: all 0.15s ease;
}
.switch .knob:before, .switch .knob:after {
border: 4px solid transparent;
border-left-color: inherit;
content: "";
display: block;
height: 0;
left: 50%;
margin-left: 2px;
margin-top: -3px;
position: absolute;
top: 50%;
width: 0;
}
.switch .knob:before {
border-left-color: transparent;
border-right-color: inherit;
margin-left: -10px;
}
.switch input {
position: absolute;
visibility: hidden;
}
.switch input:checked + .knob {
left: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<label class="switch">
<input type="checkbox" checked data-message="Checkbox 1"/>
<span class="knob"></span>
</label>
<div class="switch">
<input type="checkbox" checked data-message="Checkbox 2" />
<span class="knob"></span>
</div>
</div>
The change event fires fine on the first checkbox but not at all on the second. Is it something to do with the label sharing the event on the hidden input, whereas the div does not do this?
Testing here: https://jsfiddle.net/Twisty/947vsjpa/5/
You can see that Click events are happening on the Switch & Knob, yet not on the Input. The label element has a relationship with input. The click event upon the Label can effect the state of the Input. div does not have this relationship; therefore, the click event does not reach the invisible element.
How do you want to fix this? Use Label element for both? Capture the click event on the .switch and then trigger a click of the Input.
Consider the following: https://jsfiddle.net/Twisty/947vsjpa/18/
JavaScript
$(function() {
$('#container .switch').click(function(event) {
console.log(event.type, event.target);
event.preventDefault();
var $input = $("input[type='checkbox']", this)
$input.prop("checked", !$input.prop("checked"));
alert($input.data("message"));
});
});
This changes the property even if it's not visible and can't be clicked upon.

How do i add a Mouse Over Tooltip to the icons in HTML

I have tried to add a mouse over tooltip to the icons, but they disappear anytime i create the Style .ion-android-hand:before {
I believe there is something i am missing, can anyone help me out on this?
.ion-android-hand: {
visibility: visible;
cursor: pointer;
}
.ion-android-hand:before {
content: attr(data-text);
background-color: rgba(0, 0, 0, 0.8);
width: 14%;
left: 70%;
margin-left: 100px;
height: 10%;
color: #fff;
text-align: center;
border-radius: 5px;
display: block;
z-index: 1;
padding: 10px;
font-size: 80%;
font-style: normal;
position: absolute;
margin-top: 35px;
cursor: pointer;
}
<div class="wash-icons">
<i class="ion-android-hand" data-text="Hand free triggering system"></i>
I have tried to add a mouse over tooltip to the icons, but they disappear anytime i create the Style .ion-android-hand:before {
I believe there is something i am missing, can anyone help me out on this?
I dont know if this will help you but it is a start based on what I understood from your problem.
Hover the red square As it is going to be use for phone I recommand using :focus as well as :hover as there is no mouse on phone. Hover do not work correctly on phones
.wash-icons{
width: 20px;
height:20px;
background:red;
}
.wash-icons .ion-android-hand{
visibility: hidden;
}
.wash-icons:hover .ion-android-hand, .wash-icons:focus .ion-android-hand {
visibility: visible;
cursor: pointer;
}
.ion-android-hand:before {
content: attr(data-text);
background-color: rgba(0, 0, 0, 0.8);
/*width: 14%;*/
left: 0%;
margin-left: 20px;
/*height: 10%;*/
color: #fff;
text-align: center;
border-radius: 5px;
display: block;
z-index: 1;
padding: 10px;
font-size: 80%;
font-style: normal;
position: absolute;
margin-top: 35px;
cursor: pointer;
}
<div class="wash-icons">
<i class="ion-android-hand" data-text="Hand free triggering system"></i>
</div>
Edit:
Process of the correction
Set visibility of .ion-android-hand to visibility: hidden; by default
Change the visibility to visibile when hover its parent .wash-icons
So hover parent show your "i"
Please hover green circle to see the tooltip
First set visibility:hidden; to .ion-android-hand
.ion-android-hand{
visibility:hidden;
}
Then :hover the wash-icons to visible (Mobile phone not hover try :focus instead)
.wash-icons:hover .ion-android-hand,
.wash-icons:focus .ion-android-hand{
visibility: visible;
}
Also added some style to wash-icons for green circle.
.wash-icons{
background:#00cc00;
border-radius:30px;
width:60px;
height:60px;
position:relative;
display:flex;
align-items:center;
justify-content:center;
}
.ion-android-hand:before {
content: attr(data-text);
background-color: rgba(0, 0, 0, 0.8);
width: 100px;
left: 0;
height: 50px;
color: #fff;
text-align: center;
border-radius: 5px;
display: block;
z-index: 1;
padding: 10px;
font-size: 80%;
font-style: normal;
position: absolute;
margin-top: 35px;
cursor: pointer;
}
.ion-android-hand{
visibility: hidden;
cursor: pointer;
}
.wash-icons:hover .ion-android-hand,
.wash-icons:focus .ion-android-hand{
visibility: visible;
cursor: pointer;
}
<div class="wash-icons">me
<i class="ion-android-hand" data-text="Hand free triggering system"></i>
</div>
The top of Tooltip added arrow
Demo here
.wash-icons{
background:url(https://i.stack.imgur.com/FnfUn.png);
background-size:contain;
border-radius:50%;
width:40px;
height:40px;
padding:5px;
position:relative;
}
.ion-android-hand:before {
content: attr(data-text);
background-color: rgba(0, 0, 0, 0.8);
width: 200px;
left: 0;
top:calc(100% + 5px);
height: 20px;
color: #fff;
text-align: center;
border-radius: 5px;
display: block;
z-index: 1;
padding: 10px;
font-size: 80%;
font-style: normal;
position: absolute;
cursor: pointer;
}
.ion-android-hand{
visibility: hidden;
cursor: pointer;
}
.wash-icons:hover .ion-android-hand,
.wash-icons:focus .ion-android-hand{
visibility: visible;
cursor: pointer;
}
.ion-android-hand::after {
content: " ";
position: absolute;
top: calc(100% - 5px);
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent transparent rgba(0, 0, 0, 0.8) transparent;
}
<div class="wash-icons">
<i class="ion-android-hand" data-text="This is Toolip for Android icon"></i>
</div>

Always show tooltip at the same position from containg dive

When I hover over the first Div, the tooltip is shown further away than if I hover over the following two divs. Obviously it is because the text inside the div is larger/longer. But I don't want to show the tooltip span not depending on the hover text, but relating to the containing div of the text, so it is shown always at the same position.
jQuery is not an option for anything though but I kind of think, that it's a CSS problem anyway.
.subPhaseContainer {
float: left;
margin: 0 auto;
}
.projectItem {
margin: 4px;
border: 2px solid black;
cursor: pointer;
height: 17px;
}
.projectItem.green {
background-color: green;
color: white;
}
.projectNumber {
position: relative;
display: inline-block;
width: 80px;
}
.projectNumber .tooltiptext {
visibility: hidden;
width: fit-content;
text-align: left;
padding: 5px;
top: -1px;
position: absolute;
z-index: 1;
margin-left: 34px;
transition: opacity 0.3s;
border: 1px solid black;
}
.projectNumber .tooltiptext::after {
content: "";
position: absolute;
top: 20%;
right: 100%;
margin-top: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent black transparent transparent;
}
.projectNumber:hover .tooltiptext.green {
background-color: green;
color: white;
visibility: visible;
opacity: 1;
}
.projectNumber:hover .tooltiptext.yellow {
background-color: yellow;
visibility: visible;
opacity: 1;
}
.projectNumber:hover .tooltiptext.red {
background-color: red;
color: white;
visibility: visible;
opacity: 1;
}
<div class="subPhaseContainer">
<div class="projectItem green">
<div class="projectNumber"><span>AAAA-00</span>
<span class="tooltiptext green">Tooltip Sample</span>
</div>
</div>
<div class="projectItem green">
<div class="projectNumber">
<span>BBB-11</span>
<span class="tooltiptext green">Tooltip Sample</span>
</div>
</div>
<div class="projectItem green">
<div class="projectNumber">
<span>CCC-22</span>
<span class="tooltiptext green">Tooltip Sample</span>
</div>
</div>
</div>
You need to specify either a 'left' or 'right' position for your tooltiptext span, otherwise its left/right position will be the same as it would have been had you kept the tooltiptext span positioned relative.
So just update your CSS for the tooltiptext to this:
.projectNumber .tooltiptext {
visibility: hidden;
width: fit-content;
text-align: left;
padding: 5px;
top: -1px;
right: -100%;
position: absolute;
z-index: 1;
margin-left: 34px;
transition: opacity 0.3s;
border: 1px solid black;
}

CSS: .table-responsive class messes up tooltip's content [fiddle provided] [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I've got this problem - after adding .table-responsive class the table header tooltips got lost overflow-x: auto - Setting it off makes it alright but disables the responsivness of the table.
I've created code snippet to show you
https://jsfiddle.net/kristjanrei/74aa8x6u/
Default code for tooltip
.container {
padding: 200px;
}
.custom-tooltip-hover {
position: relative;
}
.custom-tooltip { /* hide and position tooltip */
position: absolute;
bottom: 100%;
left: 0px;
background-color: #000;
color: #fff;
line-height: initial;
visibility: hidden;
border: 1px solid #fff;
text-align: left;
padding-left: 8px;
padding-right: 8px;
padding-top: 4px;
padding-bottom: 4px;
margin-bottom: 4px;
z-index: 110;
transition-delay: 0.33s;
font-size: 13px;
font-weight: initial;
word-break: inherit;
font-size: 12px;
white-space: normal;
}
.custom-tooltip.left {
left: initial;
right: 0px;
}
.custom-tooltip:after {
content: '';
position: absolute;
top: 100%;
left: 12%;
width: 0; height: 0;
border-top: 8px solid #000000;
border-right: 8px solid transparent;
border-left: 8px solid transparent;
}
.custom-tooltip.left:after {
left: initial;
right: 12%;
}
.custom-tooltip-hover:hover .custom-tooltip {
visibility: visible;
display: inline;
transition-delay: 0.88s;
-webkit-transition-delay: 0.88s; /* Safari */
}
.break-tooltip {
word-break: break-all;
}
A snippet from jsfiddle of a broken tooltip.
Way it works every where else
I have added this on the div panel and it has worked style="overflow:visible;
.container {
padding: 200px;
}
.custom-tooltip-hover {
position: relative;
}
.custom-tooltip { /* hide and position tooltip */
position: absolute;
bottom: 100%;
left: 0px;
background-color: #000;
color: #fff;
line-height: initial;
visibility: hidden;
border: 1px solid #fff;
text-align: left;
padding-left: 8px;
padding-right: 8px;
padding-top: 4px;
padding-bottom: 4px;
margin-bottom: 4px;
z-index: 11000000;
transition-delay: 0.33s;
font-size: 13px;
font-weight: initial;
word-break: inherit;
font-size: 12px;
white-space: normal;
}
.custom-tooltip.left {
left: initial;
right: 0px;
}
.custom-tooltip:after {
content: '';
position: absolute;
top: 100%;
left: 12%;
width: 0; height: 0;
border-top: 8px solid #000000;
border-right: 8px solid transparent;
border-left: 8px solid transparent;
}
.custom-tooltip.left:after {
left: initial;
right: 12%;
}
.custom-tooltip-hover:hover .custom-tooltip {
visibility: visible;
display: inline;
transition-delay: 0.88s;
-webkit-transition-delay: 0.88s; /* Safari */
}
.break-tooltip {
word-break: break-all;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="custom-tooltip-hover">
<div>
Working header
</div>
<span class="custom-tooltip">
Tooltip for head
</span>
</div>
<div class="panel panel-default">
<div class="panel-body table-responsive" style="overflow:visible;">
<table class="table-hover">
<thead>
<tr>
<th>
<div class="custom-tooltip-hover">
<div>
Broken Header
</div>
<span class="custom-tooltip">
Tooltip for head
</span>
</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td> Content for head</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
If you want to hide some part of content with overflow, then you are able to use position:fixed for the .custom-tooltip class and place it with js.
Checkout the library tether (bootstrap also use it for tooltips), there are a lot of options, to attache the element to another element. I think it'll be much easier.