Kendo UI MVC - Display None in HtmlAttributes - kendo-asp.net-mvc

Hi I have a Kendo ComboBox like this:
#(Html.Kendo().ComboBox()
.Name("LHWR")
.HtmlAttributes(new { style = "width:150px; font-size:small; display:none" })
.BindTo(new List<SelectListItem>() {
new SelectListItem() {
Text = "Leave unchanged", Value = "0"
},
new SelectListItem() {
Text = "Deactivate", Value = "1"
},
new SelectListItem() {
Text = "Activate", Value = "2"
}
})
.SelectedIndex(0)
)
The "display: none" doesn't work, it hides the "input" tag but not the "span" tag:
<span class="k-widget k-combobox k-header" style="width: 150px; font-size: small;">
<span tabindex="-1" unselectable="on" class="k-dropdown-wrap k-state-default">
<input name="LHWR_input" class="k-input" type="text" autocomplete="off" maxlength="524288" role="combobox" aria-expanded="false" tabindex="0" aria-disabled="false" aria-readonly="false" aria-autocomplete="list" aria-owns="LHWR_listbox" aria-activedescendant="LHWR_option_selected" aria-busy="false" style="width: 100%; font-size: small;">
<span tabindex="-1" unselectable="on" class="k-select"><span unselectable="on" class="k-icon k-i-arrow-s" role="button" tabindex="-1" aria-controls="LHWR_listbox">select</span>
</span>
</span>
<input id="LHWR" name="LHWR" style="width: 150px; font-size: small; display: none;" type="text" data-role="combobox" aria-disabled="false" aria-readonly="false"></span>
And then the ComboBox is still visible.

I ran into this exact problem, and it is possible to use display: none, but you likely have something conflicting with the display, e.g. in-line styling overwriting it, etc. The quickest non-jQuery solution is to simply give it a class in the .HtmlAttributes() like so:
#(Html.Kendo().ComboBox()
.Name("LHWR")
.HtmlAttributes(new { style = "width:150px; font-size:small;", #class = "hiddenInputBoxClass" })
.BindTo(new List<SelectListItem>() {
new SelectListItem() {
Text = "Leave unchanged", Value = "0"
},
new SelectListItem() {
Text = "Deactivate", Value = "1"
},
new SelectListItem() {
Text = "Activate", Value = "2"
}
})
.SelectedIndex(0)
)
and then adding to your css stylesheet:
.hiddenInputBoxClass {
display: none;
}
This works because the class added via HtmlAttributes() will be applied to the enclosing span field, which will then hide your element.
And for reference, contrary to the other answer, the proper way to do this (according to Telerik) in jQuery is as follows:
$("#LHWR").data("kendoComboBox").wrapper.hide();

Hide it using javascript and jquery:
$(document).ready(function() {
$("#LHWR").closest(".k-widget").hide();
});

Hide the kendoDatePicker using below code
$("#kendo-date-picker-id").data("kendoDatePicker").wrapper.hide();

Related

Django show image button not functioning with for loop

My site allows users to upload bulk images. The issue is when a user is on mobile they could potentially have to scroll through 100's of images. I want to implement a show more button.
I found this demo online that I got to work
html:
<div class="container">
<div class="grid">
<div class="cell">
<img src="https://i.natgeofe.com/n/3861de2a-04e6-45fd-aec8-02e7809f9d4e/02-cat-training-NationalGeographic_1484324.jpg" class="book" />
</div>
<div class="cell">
<img src="https://i.natgeofe.com/n/3861de2a-04e6-45fd-aec8-02e7809f9d4e/02-cat-training-NationalGeographic_1484324.jpg" class="book" />
</div>
</div>
</div>
<button onclick={showMore()}>Show all books</button>
<script>
const showMore = () => {
document.querySelectorAll('.cell').forEach(c => c.style.display = 'block')
}
</script>
css:
#media screen and (min-width: 600px) {
.container{
overflow: auto;
height: (70vh);
}
.grid {
display: flex;
flex-wrap: wrap;
flex-direction: row;
}
.cell {
width: calc(50% - 2rem);
}
}
.cell {
margin: 1rem;
}
button {
display: none;
}
#media screen and (max-width: 600px) {
.cell {
display: none;
}
.cell:first-child {
display: block;
}
button {
display: inline-block;
}
}
However when I use the same code just with a for loop to display it does not work and just displays all the images.
<div class="container">
<div class="grid">
{% for images in postgallery %}
<div class="cell">
<img src="{{ images.images.url }}" class="book" />
</div>
{% endfor %}
</div>
</div>
<button onclick="{showMore()}">Show all books</button>
<script>
const showMore = () => {
document.querySelectorAll(".cell").forEach((c) => (c.style.display = "block"));
};
</script>

Open one UL #click in a loop generated menu with Vuejs

Still working on my menu and struggling with a new problem.
I want the user to be able to the LI submenus when there is a click on the UL.
The problem is that I don't see how to aim only at the linked LI elements. When I click on any UL, it opens all the LI.
An easy way could be to create different UL in HTML, but I would like to keep this short generated with a loop menu.
How can I aim at the precise UL with the #click event, to open only its child LI?
new Vue({
el: "#app",
data: {
categories: {
Atoms: ['Buttons', 'Icons'],
Molecules: [],
Organisms: [],
Templates: [],
Utilities: ['Grid']
},
openSubCategories: false,
},
})
.doc_nav {
display: flex;
justify-content: around;
}
.doc_nav__ul {
margin: 0 30px;
}
.doc_nav__li {
text-align: center;
}
.doc_nav__li:first-child {
margin-top: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<header class="doc_header">
<nav class="doc_nav">
<ul #click="openSubCategories = !openSubCategories" class="doc_nav__ul" v-for="[ category, subCategories ] in Object.entries(categories)" :key="category"> {{category}}
<template v-if="openSubCategories == true" >
<li class="doc_nav__li" v-for="subCategory in subCategories" :key="subCategory">
{{ subCategory }}
<!-- <router-link :to="subCategory"> {{ subCategory }} </router-link> -->
</li>
</template>
</ul>
</nav>
</header>
</div>
Use CSS to hide li.
I think you can handle it.
new Vue({
el: "#app",
data: {
categories: {
Atoms: ['Buttons', 'Icons'],
Molecules: [],
Organisms: [],
Templates: [],
Utilities: ['Grid']
},
currentActiveCategory: null,
},
method: {
changeClickUl(category) {
if (category == this.currentActiveCategory) this.currentActiveCategory = null
else this.currentActiveCategory = category
}
}
})
.doc_nav {
display: flex;
justify-content: around;
}
.doc_nav__ul {
margin: 0 30px;
}
.doc_nav__ul:not(visible) {
display: none;
}
.doc_nav__li {
text-align: center;
}
.doc_nav__li:first-child {
margin-top: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<header class="doc_header">
<nav class="doc_nav">
<ul #click="changeClickUl(category)" :class="{visible:currentActiveCategory==category}" class="doc_nav__ul" v-for="[ category, subCategories ] in Object.entries(categories)" :key="category"> {{category}}
<li class="doc_nav__li" v-for="subCategory in subCategories" :key="subCategory">
{{ subCategory }}
<!-- <router-link :to="subCategory"> {{ subCategory }} </router-link> -->
</li>
</ul>
</nav>
</header>
</div>
Here is the corrected and working answer of gao.xiangyang
It is using css.
A solution without css: v-if="currentActiveCategory==category"
new Vue({
el: "#app",
data: {
categories: {
Atoms: ['Buttons', 'Icons'],
Molecules: [],
Organisms: [],
Templates: [],
Utilities: ['Grid']
},
currentActiveCategory: null,
},
methods: {
displaySubCategories(category) {
if (category == this.currentActiveCategory) {
this.currentActiveCategory = null
}
else this.currentActiveCategory = category
}
}
})
.doc_nav {
display: flex;
justify-content: around;
}
.doc_nav__ul {
margin: 0 30px;
}
.doc_nav__li:not(visible) {
display: none;
}
.doc_nav__li--visible {
display: block !important;
}
.doc_nav__li {
text-align: center;
}
.doc_nav__li:first-child {
margin-top: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<header class="doc_header">
<nav class="doc_nav">
<ul #click="displaySubCategories(category)" class="doc_nav__ul" v-for="[ category, subCategories ] in Object.entries(categories)" :key="category"> {{category}}
<li :class="{'doc_nav__li--visible' : currentActiveCategory==category}" class="doc_nav__li" v-for="subCategory in subCategories" :key="subCategory">
{{ subCategory }}
<!-- <router-link :to="subCategory"> {{ subCategory }} </router-link> -->
</li>
</ul>
</nav>
</header>
</div>

Django rendering a number as a 5-stars rating

I'm building a rating system for my website. It's currently working well but I would like to improve the esthetical aspect of the system. I would like to be able to take the rating from the database and display it as a 5-stars rating. Also, if it's not overly complicated, I would like to be able to click on stars to record the rating in the database, rather than writing a number.
I'm quite new to web development. In particular, I have no experience with javascript (I only did tutorials found on internet), which I think is required to implement the functionality I'm searching for, so please gives me a little example with your response in order to make me able to understand.
For rendering the rating as stars, I have no idea how to do it. For recording the rating as stars, I thought about two solutions :
1) Using django star-ratings but I don't think I have the capabilities required to understand how it works. I already made a post to ask for help and examples about this app but I received no help so I guess I should forget this.
2) Using a form with some appropriate widget to render an IntegerInput as a 5-stars rating.
For the second solution, I already have the code, I now need a widget to replace 'Stars' in the code below but I'm not sure how to do it. Can someone help me ?
models.py
class Avis(models.Model):
note = models.IntegerField()
forms.py
class AvisForm(forms.ModelForm):
class Meta:
model = Avis
fields = ['note']
widgets = {'note': forms.NumberInput(attrs={'class': 'Stars'})}
labels = {'note': 'Note /5'}
hmtl for recording
<form method="post" action="">
{% csrf_token %}
{% for field in form %}
<div class="fieldWrapper form-group">
{{ field.label_tag }}
{{ field }}
</div>
{% endfor %}
<input type="submit" class="btn btn-lg btn-outline-primary btn-block btn-login text-uppercase font-
weight-bold mb-2" value="Envoyer mon avis" />
</form>
hmtl for displaying
{{ avis.note }}
Thanks in advance !
EDIT (my code so far for the ratings storing) :
views.py
def avis(request, id): # view for displaying and storing the form
commande = get_object_or_404(Commande, id=id)
if request.method == "POST":
form = AvisForm(request.POST)
if form.is_valid():
avis = form.save(commit = False)
avis.commande = commande
avis.save()
commande.has_avis = True
commande.save()
if commande.plat.chef.nb_avis==0:
commande.plat.chef.rating = avis.note
else:
commande.plat.chef.rating = (commande.plat.chef.rating*commande.plat.chef.nb_avis + avis.note)/(commande.plat.chef.nb_avis + 1)
commande.plat.chef.nb_avis += 1
commande.plat.chef.save()
messages.success(request, 'Votre avis a été correctement envoyé !')
return redirect(mes_commandes)
else:
form = AvisForm()
return render(request, 'actualites/avis.html', locals())
def avis2(request, id): # view for recording the rating
avis = get_object_or_404(Avis, id=id)
rating = request.POST.get('rating')
avis.note = rating
avis.save()
messages.success(request, 'Votre avis a été correctement envoyé !')
return redirect(mes_commandes)
html
<form method="post" action="">
{% csrf_token %}
{% for field in form %}
<div class="fieldWrapper form-group">
{{ field.label_tag }}
{{ field }}
</div>
{% endfor %}
<input type="submit" class="btn btn-lg btn-outline-primary btn-block btn-login text-uppercase font-weight-bold mb-2" value="Envoyer mon avis" />
</form>
<div class="rating rating2">
★
★
★
★
★
</div>
<script>
$(".rating a").on('click', function(e){
let value = $(this).data('value');
$.ajax({
url: "{% url 'avis2' %}",
type: 'POST',
data: {'rating': value},
success: function (d){
// some processing
}
})
});
</script>
forms.py
class AvisForm(forms.ModelForm):
class Meta:
model = Avis
fields = ['commentaire']
widgets = {'commentaire': forms.Textarea(attrs={'class': 'form-control'})}
I will try to answer your both of the question. For getting the rating, your can render stars and add a JS click event to that.
Code (HTML, CSS) source: https://codepen.io/GeoffreyCrofte/pen/jEkBL
$(".rating a").on('click', function(e){
let value = $(this).data('value');
$.ajax({
url: "some_url",
type: 'POST',
data: {'rating': value},
success: function (d){
// some processing
}
})
});
.rating {
width: 300px;
margin: 0 auto 1em;
font-size: 45px;
overflow:hidden;
}
.rating input {
float: right;
opacity: 0;
position: absolute;
}
.rating a,
.rating label {
float:right;
color: #aaa;
text-decoration: none;
-webkit-transition: color .4s;
-moz-transition: color .4s;
-o-transition: color .4s;
transition: color .4s;
}
.rating label:hover ~ label,
.rating input:focus ~ label,
.rating label:hover,
.rating a:hover,
.rating a:hover ~ a,
.rating a:focus,
.rating a:focus ~ a {
color: orange;
cursor: pointer;
}
.rating2 {
direction: rtl;
}
.rating2 a {
float:none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="rating rating2">
★
★
★
★
★
</div>
For Rendering the rating, you need to calculate the value first. You need to determine the number of person who rated 5, 3, ... 1 stars. Lets say there are 100's 5 star rating, 70 * 4 star, 50 * 3 star, 30 * 2 and 20 * 1 star rating. So you can determine rating by:
sum of rating / total rating
So it will be (100 * 5 + 70 * 4 + 50 * 3 + 30 * 2 + 20 * 1) / 100 + 70 + 50 + 30 + 20
So the final rating will be: 3.74
To get the width percentage: (3.74 * 100) / 5 = 74.8
Here 5 refers to total number of stars, here I am assuming that rating will be based on the scale of 5.
For rendering you will need different HTML and CSS.
Code source: https://codepen.io/Bluetidepro/pen/GkpEa
.star-ratings-css {
unicode-bidi: bidi-override;
color: #c5c5c5;
font-size: 25px;
height: 25px;
width: 100px;
margin: 0 auto;
position: relative;
padding: 0;
text-shadow: 0px 1px 0 #a2a2a2;
}
.star-ratings-css-top {
color: #e7711b;
padding: 0;
position: absolute;
z-index: 1;
display: block;
top: 0;
left: 0;
overflow: hidden;
}
.star-ratings-css-bottom {
padding: 0;
display: block;
z-index: 0;
}
.star-ratings-sprite {
background: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/2605/star-rating-sprite.png") repeat-x;
font-size: 0;
height: 21px;
line-height: 0;
overflow: hidden;
text-indent: -999em;
width: 110px;
margin: 0 auto;
}
.star-ratings-sprite-rating {
background: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/2605/star-rating-sprite.png") repeat-x;
background-position: 0 100%;
float: left;
height: 21px;
display: block;
}
<div class="star-ratings-css">
<div class="star-ratings-css-top" style="width: 74.8%">
<span>★</span><span>★</span><span>★</span><span>★</span><span>★</span></div>
<div class="star-ratings-css-bottom"><span>★</span><span>★</span><span>★</span><span>★</span><span>★</span></div>
</div>
You need to pass width from your view and in the HTML, you need to access it.
<div class="star-ratings-css-top" style="width: {{ width }}%">. I tried these code snippet, working for me and should work for you as well :)

How to re-direct to a print template using Knockout js

I'm using templates in my view and I'd like to direct the user to a print template. Common usage:
<div data-bind="template: { name: 'print' }"></div>
but I want this script to appear alone and not with other content.
Is it possible to go to my print script instead of pulling the script into a div, which is what the code above does. Thank you.
You could put a boolean around the "normal" content that hides everything else whenever the print template is active.
<div data-bind="visible: noprint()">main site</div>
Redirect to a different file that holds the print layout with its own styling.
Create your page as such that the print-css actually renders the page as expected. Make sure the print styles are always at the bottom of your css
#media print {
body {
color: #000;
background-color: #fff;
}
}
A bit more advanced is working with components, you could use the same data for displaying everything you need but when the user expects a printable view just switch out the screenlayout-component to the printlayout-component
screen
print
<div data-bind="component: layoutType"></div>
Here's what I ended up doing...
var viewModel = {
selectedTemplate: ko.observable('ViewContent'),
subTemplate: function (item) {
this.selectedTemplate(item);
},
goBack: function () {
this.selectedTemplate('ViewContent');
},
printLandscape: function () {
this.selectedTemplate('PrintContent');
alert("Please change page orientation to Landscape");
javascript: window.print();
},
}
ko.applyBindings(viewModel);
.print {
margin: 0px;
padding: 0px;
width: 900px; /* or width: 9.5in; */
height: 670px; /* height: 7in; */
clear: both;
page-break-after: always;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script id="getContent" type="text/html">
<!-- ko if: ($root.selectedTemplate() == "ViewContent") -->
<div data-bind="template: { name: 'viewContent' }"></div>
<!-- /ko -->
<!-- ko if: ($root.selectedTemplate() == "PrintContent") -->
<div data-bind="template: { name: 'printContent' }"></div>
<!-- /ko -->
</script>
<script id="viewContent" type="text/html">
<div>Here's the view or display content</div>
Print
</script>
<script id="printContent" type="text/html">
<div>Print | Back</div>
<div class="print">Here's the print content</div>
</script>
<div data-bind="template: { name: 'getContent' }"></div>

Hide Show content-list with only CSS, no javascript used

I've been searching for a good trick to make a Hide/Show content or a list with only CSS and no javascript.
I've managed to make this action:
<!DOCTYPE html>
<head>
<style>
#cont {display: none; }
.show:focus + .hide {display: inline; }
.show:focus + .hide + #cont {display: block;}
</style>
</head>
<body>
<div>
[Show]
/ [Hide]
<div id="cont">Content</div>
</div>
</body>
</html>
Demo here: http://jsfiddle.net/6W7XD/
And it's working but not as it should. Here is the problem:
When the content is shown, you can hide it by clicking "anywhere on the page". How to disable that? how to hide content "only" by clicking hide?
Thank you in advance!
I wouldn't use checkboxes, i'd use the code you already have
DEMO http://jsfiddle.net/6W7XD/1/
CSS
body {
display: block;
}
.span3:focus ~ .alert {
display: none;
}
.span2:focus ~ .alert {
display: block;
}
.alert{display:none;}
HTML
<span class="span3">Hide Me</span>
<span class="span2">Show Me</span>
<p class="alert" >Some alarming information here</p>
This way the text is only hidden on click of the hide element
This is going to blow your mind: Hidden radio buttons.
input#show, input#hide {
display:none;
}
span#content {
display:none;
}
input#show:checked ~ span#content {
display:block;
}
input#hide:checked ~ span#content {
display:none;
}
<label for="show">
<span>[Show]</span>
</label>
<input type=radio id="show" name="group">
<label for="hide">
<span>[Hide]</span>
</label>
<input type=radio id="hide" name="group">
<span id="content">Content</span>
I used a hidden checkbox to persistent view of some message. The checkbox could be hidden (display:none) or not. This is a tiny code that I could write.
You can see and test the demo on JSFiddle
HTML:
<input type=checkbox id="show">
<label for="show">Help?</label>
<span id="content">Do you need some help?</span>
CSS:
#show,#content{display:none;}
#show:checked~#content{display:block;}
Run code snippet:
#show,#content{display:none;}
#show:checked~#content{display:block;}
<input id="show" type=checkbox>
<label for="show">Click for Help</label>
<span id="content">Do you need some help?</span>
http://jsfiddle.net/9s8scbL7/
There is 3 rapid examples with pure CSS and without javascript where the content appears "on click", with a "maintained click" and a third "onhover" (all only tested in Chrome). Sorry for the up of this post but this question are the first seo result and maybe my contribution can help beginner like me
I think (not tested) but the advantage of argument "content" that you can add great icon like from Font Awesome (its \f-Code) or an hexadecimal icon in place of the text "Hide" and "Show" to internationalize the trick.
example link http://jsfiddle.net/MonkeyTime/h3E9p/2/
<style>
label { position: absolute; top:0; left:0}
input#show, input#hide {
display:none;
}
span#content {
display: block;
-webkit-transition: opacity 1s ease-out;
transition: opacity 1s ease-out;
opacity: 0;
height: 0;
font-size: 0;
overflow: hidden;
}
input#show:checked ~ .show:before {
content: ""
}
input#show:checked ~ .hide:before {
content: "Hide"
}
input#hide:checked ~ .hide:before {
content: ""
}
input#hide:checked ~ .show:before {
content: "Show"
}
input#show:checked ~ span#content {
opacity: 1;
font-size: 100%;
height: auto;
}
input#hide:checked ~ span#content {
display: block;
-webkit-transition: opacity 1s ease-out;
transition: opacity 1s ease-out;
opacity: 0;
height: 0;
font-size: 0;
overflow: hidden;
}
</style>
<input type="radio" id="show" name="group">
<input type="radio" id="hide" name="group" checked>
<label for="hide" class="hide"></label>
<label for="show" class="show"></label>
<span id="content">Lorem iupsum dolor si amet</span>
<style>
#show1 { position: absolute; top:20px; left:0}
#content1 {
display: block;
-webkit-transition: opacity 1s ease-out;
transition: opacity 1s ease-out;
opacity: 0;
height: 0;
font-size: 0;
overflow: hidden;
}
#show1:before {
content: "Show"
}
#show1:active.show1:before {
content: "Hide"
}
#show1:active ~ span#content1 {
opacity: 1;
font-size: 100%;
height: auto;
}
</style>
<div id="show1" class="show1"></div>
<span id="content1">Ipsum Lorem</span>
<style>
#show2 { position: absolute; top:40px; left:0}
#content2 {
display: block;
-webkit-transition: opacity 1s ease-out;
transition: opacity 1s ease-out;
opacity: 0;
height: 0;
font-size: 0;
overflow: hidden;
}
#show2:before {
content: "Show"
}
#show2:hover.show2:before {
content: "Hide"
}
#show2:hover ~ span#content2 {
opacity: 1;
font-size: 100%;
height: auto;
}
/* extra */
#content, #content1, #content2 {
float: left;
margin: 100px auto;
}
</style>
<div id="show2" class="show2"></div>
<span id="content2">Lorem Ipsum</span>
This is what I've used recently.
CSS
div#tabs p{display:none;}
div#tabs p.tab1:target {display:block;}
div#tabs p.tab2:target {display:block;}
div#tabs p.tab3:target {display:block;}
HTML
<div id='tabs'>
<h2 class="nav-tab-wrapper">
Pages
Email
Support
</h2>
<p id='tab1' class='tab1'>Awesome tab1 stuff</p>
<p id='tab2' class='tab2'>Tab2 stuff</p>
<p id='tab3' class='tab3'>Tab3 stuff</p>
</div>
https://jsfiddle.net/hoq0djwc/1/
Hope it helps somewhere.
Nowadays (2020) you can do this with pure HTML5 and you don't need JavaScript or CSS3.
<details>
<summary>Put your summary here</summary>
<p>Put your content here!</p>
</details>
First, thanks to William.
Second - i needed a dynamic version. And it works!
An example:
CSS:
p[id^="detailView-"]
{
display: none;
}
p[id^="detailView-"]:target
{
display: block;
}
HTML:
Show View1
<p id="detailView-1">View1</p>
Show View2
<p id="detailView-2">View2</p>
The answer below includes changing text for "show/hide", and uses a single checkbox, two labels, a total of four lines of html and five lines of css. It also starts out with the content hidden.
Try it in JSFiddle
HTML
<input id="display-toggle" type=checkbox>
<label id="display-button" for="display-toggle"><span>Display Content</span></label>
<label id="hide-button" for="display-toggle"><span>Hide Content</span></label>
<div id="hidden-content"><br />Hidden Content</div>
CSS
label {
background-color: #ccc;
color: brown;
padding: 15px;
text-decoration: none;
font-size: 16px;
border: 2px solid brown;
border-radius: 5px;
display: block;
width: 200px;
text-align: center;
}
input,
label#hide-button,
#hidden-content {
display: none;
}
input#display-toggle:checked ~ label#display-button {
display: none;
}
input#display-toggle:checked ~ label#hide-button {
display: block;
background-color: #aaa;
color: #333
}
input#display-toggle:checked ~ #hidden-content {
display: block;
}
I've got another simple solution:
HTML:
Hide Me
Show Me
<p id="alert" class="alert" >Some alarming information here</p>
CSS:
body { display: block; }
p.alert:target { display: none; }
Source: http://css-tricks.com/off-canvas-menu-with-css-target/
I know it's an old post but what about this solution (I've made a JSFiddle to illustrate it)... Solution that uses the :after pseudo elements of <span> to show/hide the <span> switch link itself (in addition to the .alert message it must show/hide). When the pseudo element loses it's focus, the message is hidden.
The initial situation is a hidden message that appears when the <span> with the :after content : "Show Me"; is focused. When this <span> is focused, it's :after content becomes empty while the :after content of the second <span> (that was initially empty) turns to "Hide Me". So, when you click this second <span> the first one loses it's focus and the situation comes back to it's initial state.
I started on the solution offered by #Vector I kept the DOM'situation presented ky #Frederic Kizar
HTML:
<span class="span3" tabindex="0"></span>
<span class="span2" tabindex="0"></span>
<p class="alert" >Some message to show here</p>
CSS:
body {
display: inline-block;
}
.span3 ~ .span2:after{
content:"";
}
.span3:focus ~ .alert {
display:block;
}
.span3:focus ~ .span2:after {
content:"Hide Me";
}
.span3:after {
content: "Show Me";
}
.span3:focus:after {
content: "";
}
.alert {
display:none;
}
Just wanted to illustrate, in the context of nested lists, the usefulness of the hidden checkbox <input> approach #jeffmcneill recommends — a context where each shown/hidden element should hold its state independently of focus and the show/hide state of other elements on the page.
Giving values with a common set of beginning characters to the id attributes of all the checkboxes used for the shown/hidden elements on the page lets you use an economical [id^=""] selector scheme for the stylesheet rules that toggle your clickable element’s appearance and the related shown/hidden element’s display state back and forth. Here, my ids are ‘expanded-1,’ ‘expanded-2,’ ‘expanded-3.’
Note that I’ve also used #Diepen’s :after selector idea in order to keep the <label> element free of content in the html.
Note also that the <input> <label> <div class="collapsible"> sequence matters, and the corresponding CSS with + selector instead of ~.
jsfiddle here
.collapse-below {
display: inline;
}
p.collapse-below::after {
content: '\000A0\000A0';
}
p.collapse-below ~ label {
display: inline;
}
p.collapse-below ~ label:hover {
color: #ccc;
}
input.collapse-below,
ul.collapsible {
display: none;
}
input[id^="expanded"]:checked + label::after {
content: '\025BE';
}
input[id^="expanded"]:not(:checked) + label::after {
content: '\025B8';
}
input[id^="expanded"]:checked + label + ul.collapsible {
display: block;
}
input[id^="expanded"]:not(:checked) + label + ul.collapsible {
display: none;
}
<ul>
<li>single item a</li>
<li>single item b</li>
<li>
<p class="collapse-below" title="this expands">multiple item a</p>
<input type="checkbox" id="expanded-1" class="collapse-below" name="toggle">
<label for="expanded-1" title="click to expand"></label>
<ul class="collapsible">
<li>sub item a.1</li>
<li>sub item a.2</li>
</ul>
</li>
<li>single item c</li>
<li>
<p class="collapse-below" title="this expands">multiple item b</p>
<input type="checkbox" id="expanded-2" class="collapse-below" name="toggle">
<label for="expanded-2" title="click to expand"></label>
<ul class="collapsible">
<li>sub item b.1</li>
<li>sub item b.2</li>
</ul>
</li>
<li>single item d</li>
<li>single item e</li>
<li>
<p class="collapse-below" title="this expands">multiple item c</p>
<input type="checkbox" id="expanded-3" class="collapse-below" name="toggle">
<label for="expanded-3" title="click to expand"></label>
<ul class="collapsible">
<li>sub item c.1</li>
<li>sub item c.2</li>
</ul>
</li>
</ul>
A very easy solution from cssportal.com
If pressed [show], the text [show] will be hidden and other way around.
This example does not work in Chrome, I don't why...
.show {
display: none;
}
.hide:focus + .show {
display: inline;
}
.hide:focus {
display: none;
}
.hide:focus ~ #list { display:none; }
#media print {
.hide, .show {
display: none;
}
}
<div><a class="hide" href="#">[hide]</a> <a class="show" href="#">[show]</a>
<ol id="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ol>
</div>
There is a pure HTML solution! Try the <details> element.
Implementation details from MDN: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary
And a try it out example from W3: https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_details
Browser support info is here: https://caniuse.com/details
After reading all the answers, I made this for whoever may still be looking for the trick: https://jsfiddle.net/Junip/do5xbkr6.
You now have the four ways to interact with links with CSS:
No form elements, no summary-details html tags, zero scripting.
#btn1::before { content: "Hover"; }
#btn1:hover::before { content: "Move"; }
#btn1:hover ~ #content { display: block; }
#btn2::before { content: "Hold down"; }
#btn2:active::before { content: "Release"; }
#btn2:active ~ #content { display: block; }
#btn2:active { opacity: 0; }
#btn3 a::before { content: "Click"; }
#btn3 a:focus::before { content: "Click away"; }
#btn3:focus-within ~ #content { display: block; }
#content {
display: none;
position: absolute;
top: 30%;
}
[id^="btn"] a {
text-decoration: none;
color: black;
}
#btn4 a[href="#revert"] { display: none; }
#content:target { display: block; }
#content:target ~ #btn4 a[href="#content"] { display: none; }
#content:target ~ #btn4 a[href="#revert"] { display: block; }