In the following html the .pricing-item has a border which appears when it is hovered (.pricing-item:hover::after). I am trying to set it so that when the button (pricing-button btn-primary) is hovered, the css for the .pricing-item border is set to '0px;'.
<div class="pricing-item">
<div class="pricing-icon"></div>
<h3 class="pricing-title">Title</h3>
<div class="pricing-price"><span class="pricing-currency">$</span>200<span class="pricing-period">/ year</span></div>
<ul class="pricing-feature-list">
<li class="pricing-feature">Feature</li>
<li class="pricing-feature">Feature</li>
<li class="pricing-feature">Feature</li>
<li class="pricing-feature">Feature</li>
</ul>
<button class="pricing-button btn btn-primary">Choose plan</button>
In css file tried using ~ or + to make one class affect the other but just not getting it right. Any help would be appreciated. Thanks.
Here is a trick you can do, to achieve what you want.
.pricing-item-wrapper {
position: relative;
}
.pricing-item {
padding-bottom: 30px;
border: 1px solid red;
z-index: 1;
}
.pricing-button {
position: absolute;
bottom: 10px;
left: 1px;
z-index: 2;
}
.pricing-button:hover + .pricing-item {
border: 1px solid transparent;
}
<div class="pricing-item-wrapper">
<button class="pricing-button btn btn-primary">Choose plan</button>
<div class="pricing-item">
<div class="pricing-icon"></div>
<h3 class="pricing-title">Title</h3>
<div class="pricing-price">
<span class="pricing-currency">$</span>
200
<span class="pricing-period">/ year</span>
</div>
<ul class="pricing-feature-list">
<li class="pricing-feature">Feature</li>
<li class="pricing-feature">Feature</li>
<li class="pricing-feature">Feature</li>
<li class="pricing-feature">Feature</li>
</ul>
</div>
</div>
With your current HTML code, the short answer is : you can't.
The reason is : you try to access a parent element with CSS, which is not possible.
<div class="pricing-item">
...
<button class="pricing-button btn btn-primary">Choose plan</button>
</div>
You'll have to change something in your HTML, e.g :
<div class="pricing-item">
...
<button class="pricing-button btn btn-primary">Choose plan</button>
<div class="pricing-item-border"></div>
</div>
So it will make things a lot easier :
.pricing-item:hover .pricing-item-border { /* Display the border */}
.pricing-item:hover .pricing-button:hover + .pricing-item-border { /* Hide the border */}
Unfortunately no CSS selectors can go up the dom.. For this you'd have to use JS.
You could add that hover effect on pricing-item but not from just hovering on the button within that element.
A simple JS version would be:
$('.pricing-button.btn-primary').hover(
function() {
$(this).parent().css('border', '2px solid black');
},
function() {
$(this).parent().css('border', 'none');
}
);
CSS
.pricing-item.no-border{
border: 0px;
}
JS
$(".pricing-button".on({
mouseenter: function () {
//stuff to do on mouse enter
$(this).parents(".pricing-item").addClass("no-border");
},
mouseleave: function () {
//stuff to do on mouse leave
$(this).parents(".pricing-item").removeClass("no-border");
}
});
Related
I want to make a hidden context menu to display multiple genre selections. I want to customize the input checkboxes so that it looks like this:
this image is my required finished layout
It works fine without the label elements in the unordered list elements, however I need the label to toggle the checkbox. This is my current (incorrect) layout:
this image is what I have achieved so far
I have tried many things, including setting:
position: relative/absolute
display: flexbox/inline-block
widths and heights
How do I use an unordered list to display labeled inputs with customized checkboxes using only CSS and HTML?
<div class="col-md-12 col-lg-4 text-lg-right mt-md-4 mt-lg-0">
<div class="d-flex-column w-100" id="genre-bar">
<!-- always visible selections bar -->
<div class="row">
<div class="col-12 mb-3 d-flex text-align-right">
<span class="w-100 genre-bar-display text-align-right align-items-center"><i class="fas fa-chevron-down"></i></span>
</div>
</div>
<div class="genre-hidden-section px-3">
<!-- Multiple selector -->
<div class="row">
<div class="col-6 text-left">
<ul id="first-genre-list" class="genre-list">
<!-- This is populated by the #foreach below using JS -->
</ul>
</div>
<div class="col-6 text-left">
<ul id="second-genre-list" class="genre-list">
<!-- This is populated by the #foreach below using JS -->
</ul>
</div>
</div>
</div>
</div>
<!-- This div gets emptied and removed by JS immediately -->
<div id="select-close-books-genre" style="display:none;">
<ul>
#foreach (GenreModel genre in Model.Genres)
{
<li class="genre-checkbox-container">
<label>
#genre.Name
<span class="genre-checkmark"></span>
<input type="checkbox" value="#genre.Id">
</label>
</li>
}
</ul>
</div>
</div>
li input {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}
.genre-checkmark {
display: inline-block;
top: 0;
left: 0;
height: 13px;
width: 13px;
border: 1px black solid;
border-radius: 3px;
background-color: white;
}
.genre-list {
display:flex;
flex-wrap:wrap;
}
.genre-checkbox-container {
flex-grow: 1;
}
.genre-checkbox-container:hover span {
background-color: #ccc;
}
.genre-checkbox-container input:checked ~ .genre-checkmark {
background-color: #30d9c8;
}
const genreListDiv = $("#select-close-books-genre")[0];
const genreList = Array.from(genreListDiv.firstElementChild.children);
genreListDiv.remove();
console.log(genreList)
for (let i = 0; i < genreList.length/2; i++) {
$('#first-genre-list')[0].appendChild(genreList[i]);
};
for (let i = Math.ceil(genreList.length/2); i < genreList.length; i++) {
$('#second-genre-list')[0].appendChild(genreList[i]);
};
// Open and close the genre selector box
$("#genre-bar").on('click', function(event) {
$("#genre-bar").addClass("genre-bar-open");
$('body').on('click', function () {
$('#genre-bar').removeClass("genre-bar-open");
});
$('#genre-bar').on('click', function (event) {
event.stopPropagation();
});
});
I want to implement a list to which new items can be added with buttons. One button at the top of the list to prepend new items, another one at the bottom to append new items.
HTML:
<div>
<div id="list">
<button class="addbtn">prepend item</button>
<ul id="items"></ul>
<button class="addbtn">append item</button>
</div>
</div>
The buttons are only visible when hovering the div containing the list (via css :hover selector).
CSS:
.addbtn {
display: none;
}
#list:hover .addbtn {
display: block;
}
Is there a way (without using JS, only with CSS) to only show the append button, but not the prepend button, when the list is empty?
If the list contains at least one item, both buttons should be shown.
JSFiddle: https://jsfiddle.net/uLmzom18/
Edit: here's the JSFiddle with the working solution: https://jsfiddle.net/khu7bahm/
You can not influence with CSS an element that is upwards of the other in the DOM flow.
But you can trick it: inverse the order of the elements in the HTML, and rearrange them using flex
ul:empty ~ .addbtn {
background-color: lightgreen;
}
#list, #list2 {
display: inline-flex;
flex-direction: column-reverse;
}
<div>
<div id="list">
<button class="addbtn">prepend item</button>
<ul id="items"></ul>
<button class="addbtn">append item</button>
</div>
</div>
<div>
<div id="list2">
<button class="addbtn">prepend item</button>
<ul id="items">
<li>1</li>
<li>2</li>
</ul>
<button class="addbtn">append item</button>
</div>
</div>
If you may use display:flex for your #list, you could reverse the order of the buttons and use the css sibling selector +
See this fiddle: https://jsfiddle.net/sb7zewp6/1/
If you need more info about this I can extend this answer, but I think this is only needed if display:flex is an option.
More info about display:flex usage at caniuse.com
$(".addbtn").click(function() {
if($(this).hasClass("prepend"))
$("#items").prepend($("<li>").text("prepended item " + $("#items").children().length));
else
$("#items").append($("<li>").text("appended item " + $("#items").children().length));
});
#list {
width: 300px;
min-height: 10em;
background-color: #fff;
display:flex;
}
.addbtn {
display: none;
}
#items:empty+.addbtn {
display:none !important;
}
#list:hover .addbtn {
display: block;
}
.addbtn.append {
order:3;
}
#items {
order:2;
outline:1px solid red;
}
.addbtn.prepend {
order:1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div id="list">
<button class="addbtn append">append item</button>
<ul id="items"></ul>
<button class="addbtn prepend">prepend item</button>
</div>
</div>
You cannot test the emptiness of an element using CSS as it doesn't have the possibility to traverse up. What you can do is, if you use jQuery, it is possible.
If you want a pure CSS based solution for your current HTML, then no!
However, if you are using some invalid HTML, it might work:
#items .addbtn:last-child {
display: none;
}
<div>
<div id="list">
<ul id="items">
<button class="addbtn">prepend item</button>
</ul>
<button class="addbtn">append item</button>
</div>
</div>
Here, I have given the addbtn directly inside the <ul>, which is wrong. But if you are determined, we can make it better:
#items .btnAdd {
margin-left: -40px;
margin-bottom: 20px;
}
#items .btnAdd:last-child {
display: none;
}
<p>No Prepend Button</p>
<div>
<div id="list">
<ul id="items">
<li class="btnAdd"><button class="addbtn">prepend item</button></li>
</ul>
<button class="addbtn">append item</button>
</div>
</div>
<hr />
<p>Prepend Button Shown</p>
<div>
<div id="list">
<ul id="items">
<li class="btnAdd"><button class="addbtn">prepend item</button></li>
<li>One item</li>
</ul>
<button class="addbtn">append item</button>
</div>
</div>
The final snippet is a pure CSS based solution.
Here is my code:
a) I have a row of buttons at the top formatted horizontally as such:
HTML:
<ul class="nav">
Work
Volunteer
Education
Skills
References
Images
</ul>
b) I have div blocks each displaying a paragraph:
<div class="jobs">
<h2>text</h2>
<h3>text</h3>
<h4>text</h4>
</div>
c) I want the CSS to not display the jobs div yet:
.jobs {
display: none;
}
d) Now that I hover over the first button I want the jobs div to display:
.button1:hover+.jobs {
display: block
}
e) Repeat for all other div sections
.volunteer {
display: none;
}
.button2:hover+.volunteer {
display:block
}
You will need to markup HTML differently.
.jobs, .volunteer {
display: none;
}
.button1:hover+.jobs, .button2:hover+.volunteer {
display: block;
/* position the divs under the navigation links */
position: absolute;
top: 120px;
}
<ul class="nav">
<li>
Work
<div class="jobs">
<h2>h2 jobs</h2>
<h3>h3 jobs</h3>
<h4>h4 jobs</h4>
</div>
</li>
<li>
Volunteer
<div class="volunteer">
<h2>h2 volunteer</h2>
<h3>h3 volunteer</h3>
<h4>h4 volunteer</h4>
</div>
</li>
<li> Education</li>
<li> Skills</li>
<li> References</li>
<li> Images</li>
</ul>
This is impossible, as described, with your current HTML, with only HTML and CSS (though only perhaps until the reference and :matches() pseudo-selectors arrive). However, if, rather than :hover you'd be willing to work with clicks on the list-elements, it can be done (without JavaScript). Given the corrected HTML:
<ul class="nav">
<li>Work
</li>
<li> Volunteer
</li>
<!-- and so on... -->
</ul>
<div id="details">
<div id="jobs"></div>
<div id="volunteer"></div>
<!-- and so on... -->
</div>
The following CSS will show the relevant div element once the <a> element has been clicked on (note that the use of an id is essential for this to work):
#details > div {
/* to hide the eleemnt(s) initially: */
display: none;
}
#details > div:target {
/* to show the relevant element once the relevant link is clicked: */
display: block;
}
#details > div[id]::after {
content: attr(id);
}
#details > div {
display: none;
}
#details > div:target {
display: block;
}
<ul class="nav">
<li>Work
</li>
<li> Volunteer
</li>
<li> Education
</li>
<li> Skills
</li>
<li> References
</li>
<li> Images
</li>
</ul>
<div id="details">
<div id="jobs"></div>
<div id="volunteer"></div>
<div id="education"></div>
<div id="skills"></div>
<div id="references"></div>
<div id="images"></div>
</div>
With plain JavaScript, on the other hand, it can be achieved with:
// the 'e' argument is automatically to the function by addEventListener():
function toggleRelevant (e) {
// caching the 'this' element:
var self = this,
// finding the div element with a class equal to the href of the 'a' element
// (though we're stripping off the leading '#':
relevantElement = document.querySelector('div.' + self.getAttribute('href').substring(1) );
// if the event we're responding to is 'mouseover' we set the display of the
// found div to 'block', otherwise we set it to 'none':
relevantElement.style.display = e.type === 'mouseover' ? 'block' : 'none';
}
// finding all the a elements that are in li elements:
var links = document.querySelectorAll('li a');
// iterating over those a elements, using Array.prototype.forEach:
[].forEach.call(links, function(linkElem){
// adding the same event-handler for both mouseover and mouseout:
linkElem.addEventListener('mouseover', toggleRelevant);
linkElem.addEventListener('mouseout', toggleRelevant);
});
function toggleRelevant(e) {
var self = this,
relevantElement = document.querySelector('div.' + self.getAttribute('href').substring(1));
relevantElement.style.display = e.type === 'mouseover' ? 'block' : 'none';
}
var links = document.querySelectorAll('li a');
[].forEach.call(links, function(linkElem) {
linkElem.addEventListener('mouseover', toggleRelevant);
linkElem.addEventListener('mouseout', toggleRelevant);
});
div[class] {
display: none;
}
div[class]::before {
content: attr(class);
color: #f00;
border: 1px solid #f00;
padding: 0.2em;
}
<ul class="nav">
<li>Work
</li>
<li> Volunteer
</li>
<!-- and so on... -->
</ul>
<div class="jobs">
<h2>text</h2>
<h3>text</h3>
<h4>text</h4>
</div>
<div class="volunteer">
<h2>text</h2>
<h3>text</h3>
<h4>text</h4>
</div>
<!-- and so on... -->
I don't think this is do able in css since display blocks (job, volonteer, ...) and button are not parent. But in jQuery this is fairly simple :
$('.buttonX').hover(
function() {
// Styles to show the box
$('.boxX').css(...);
},
function () {
// Styles to hide the box
$('.boxX').css(...);
}
);
It sounds like you're trying to do some kind of a tab menu where pressing a specific button shows a different content. Here's a SO page that describes how it's done: How to make UL Tabs with only HTML CSS
I'm trying to implement auto-complete inside a form item, where as the user types it creates a dropdown menu with a list of suggestions, which are clickable. This is done inside the Ionic Framework.
I've made a codepen to demonstrate what I want. (look at the auto-complete field, and the grey hidden box below it)
http://codepen.io/pbernasconi/pen/Cgobi
My dropdown:
<div class="list">
<label class="item item-input item-stacked-label">
<span class="input-label">License #</span>
<input type="text" placeholder="AUTO COMPLETE FIELD">
<div class="input-dropdown">
<ul class="input-dropdown-menu">
<li>...</li>
</ul>
</div>
</label>
</div>
My CSS:
.input-dropdown {
position: absolute;
background: grey;
border: solid 1px #000;
z-index: 1001;
overflow: visible;
}
.input-dropdown-menu {
}
This issue is that position: absolute doesn't allow me to overlay over the list item below the auto-complete field, as you can see in the codepen.
Here's an example of a solution, which for some reason doesn't work for me.
Does anyone know how to implement this dropdown to overlay over it's parent's?
The label item overflow is hidden and the dropdown list is inside it, so you can't see it.
// jquery code
$(document).ready(function() {
$("#test").focus(function(){
$(".input-dropdown-menu").show();
});
$("#test").mouseleave(function(){
$(".input-dropdown-menu").hide();
});
});
//use css
input-dropdown {
position: absolute;
background: grey;
border: solid 1px #000;
z-index: 1001;
overflow: visible;
margin-left:65px;
}
.input-dropdown-menu {
display:none;
}
//use html
<div class="list">
<label class="item item-input item-stacked-label">
<span class="input-label">License #</span>
<input type="text" placeholder="AUTO COMPLETE FIELD" id ="test">
<div class="input-dropdown">
<ul class="input-dropdown-menu">
<li>111</li>
<li>111</li>
<li>111</li>
</ul>
</div>
Can anyone tell me how to disable a div or elements inside a div?
I have a jstree in my div and I want to disable the div/jstree.
Thanks!
I made a simple example for you here
Basically, it creates a div over your jstree's one so that it is disabled from user interactions.
I guess you can make it visually better, but i think this gives you the idea.
I also checked that there is no strigth way to disable a jstree, even if it could be usefull.
Maybe you'd want to ask the dev in google group...
HTML Code:
<button id="disable">Disable</button>
<button id="enable">Enable</button>
<div id="jstree-wrapper">
<div id="demo" style="height:100px;">
<ul>
<li id="node_1_id">
<a>Root node 1</a>
<ul>
<li id="child_node_1_id">
<a>Child node 1</a>
</li>
<li id="child_node_2_id">
<a>Child node 2</a>
</li>
</ul>
</li>
</ul>
<ul>
<li><a>Team A's Projects</a>
<ul>
<li><a>Iteration 1</a>
<ul>
<li><a>Story A</a></li>
<li><a>Story B</a></li>
<li><a>Story C</a></li>
</ul>
</li>
<li><a>Iteration 2</a>
<ul>
<li><a>Story D</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div id="disabler"></div>
</div>
CSS code:
#jstree-wrapper {
position: relative;
}
#disabler {
position: absolute;
top: 0px;
left: 0px;
background-color: black;
opacity: 0.5;
}
JS Code:
$(document).ready(function() {
$("#demo").jstree();
$("#disable").on("click", function() {
$("#disabler").css("width", $("#demo").width());
$("#disabler").css("height", $("#demo").height());
});
$("#enable").on("click", function() {
$("#disabler").css("width", "0px");
$("#disabler").css("height", "0px");
});
});
Here's a very good example I didn't find done so simple and good anywhere else. In this example you can simulate the 'disabled' attribute only by adding CSS style as I entered in the code snippet. It disables by using the CSS "visible:hidden", and adds a translucent mask to cover the whole div area and disable anything inside it. You can choose to comment out the 'Visibility:hidden' to be able to see the elements behind the mask, but then they will be tabable, if you don't mind them hidden then uncomment that style.
function disable(elementId, enabling) {
el = document.getElementById(elementId);
if (enabling) {
el.classList.remove("masked");
} else
{
el.classList.add("masked");
}
}
.masked {
position: relative;
pointer-events: none;
display: inline-block;
//visibility:hidden; /* Uncomment this for complete disabling */
}
.masked::before {
position: absolute;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
visibility: visible;
opacity: 0.2;
background-color: black;
content: "";
}
<button onclick="alert('Now, click \'OK\' then \'Tab\' key to focus next button.\nThen click \'Enter\' to activate it.');">Test</button>
<div id="div1" style="display:inline-block" class="masked">
<button onclick="alert('Sample button was clicked.')">Maskakable</button>
<button onclick="alert('Sample button was clicked.')">Maskakable</button><br/>
<br/>
<button onclick="alert('Sample button was clicked.')">Maskakable</button>
<button onclick="alert('Sample button was clicked.')">Maskakable</button>
</div>
<button>Dummy</button>
<br/>
<br/>
<br/>
<button id="enableBtn" onclick="disable('div1',true);disable('enableBtn',false);disable('disableBtn',true);">Enable</button>
<button id="disableBtn" onclick="disable('div1',false);disable('enableBtn',true);disable('disableBtn',false);" class="masked">Disable</button>