SCSS: Check if the element has the attribute - if-statement

I need to check if the element has an attribute for the styles to apply on mobile devices(or in responsive mode). For example:
<tr>
<td>Some text here</td>
<td data-content="Hello there">Other text here</td>
<td data-content="Hi there">Final text here</td>
</tr>
Browser:
------------------------------------------------------
| Some text here | Other text here | Final text here |
------------------------------------------------------
Mobile devices (Required output):
--------------------------------
| Some text here |
| Hello there: Other text here |
| Hi there: Final text here |
--------------------------------
SCSS:
tr {
td {
...
#if (&[data-content]) {
&:before {
content: attr(data-content) ":";
float: left;
font-size: 12px;
font-weight: bold;
margin: 0 5px 0 0;
text-transform: uppercase;
}
}
}
}
Mobile devices (Current output):
--------------------------------
| : Some text here |
| Hello there: Other text here |
| Hi there: Final text here |
--------------------------------

I found the solution. Apparently it was quite easy...
SCSS:
tr {
td {
...
&[data-content] {
&:before {
content: attr(data-content) ":";
float: left;
font-size: 12px;
font-weight: bold;
margin: 0 5px 0 0;
text-transform: uppercase;
}
}
}
}
Current output:
--------------------------------
| Some text here |
| Hello there: Other text here |
| Hi there: Final text here |
--------------------------------

Related

Display rows in 2 columns

I would like to display my row on 2 columns,
but for a reason it is only displaying the first entry on 2 rows.('name' on 1 row /'grouped_id' other row.
Not all entries of my database.
I missed something know with $row=.
Can you help me ? I would like display 'name' 'grouped_id' on each row:
my code
<title>TITLE</title>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght#700;800;900&display=swap" rel="stylesheet">
<style>
body {background-color: #000000;}
table {
background-color: #000000;
border-collapse: collapse;
width: 100%;
}
table, .table {
color: #fff;
font-family: "Montserrat", sans-serif;
font-size: 18px;
font-weight:800;
font-weight:Extra-bold;
}
tr:nth-child(even) {
background-color: #60451e;
}
</style>
<div class="container">
<div class="row">
<?php
include_once("inc/db_connect.php");
$sqlQuery = "SELECT name, GROUP_CONCAT(id ORDER BY id SEPARATOR ' | ') as grouped_id FROM developers GROUP BY name";
$resultSet = mysqli_query($conn, $sqlQuery) or die("database error:". mysqli_error($conn));
?>
<table id="editableTable" class="table table-bordered">
<tbody>
<?php
// represents your database rows
$rows = mysqli_fetch_array($resultSet);
$length = count($rows);
$halfIndex = ceil($length / 2);
$currentRow = 0;
while ($currentRow < $halfIndex) {
$leftIndex = $currentRow;
$rightIndex = $halfIndex + $currentRow;
$leftColumn = $rows[$leftIndex] ?? '--';
$rightColumn = $rows[$rightIndex] ?? '--';
echo "<tr>";
echo "<td>{$leftColumn}</td>";
echo "<td>{$rightColumn}</td>";
echo "</tr>";
$currentRow++;
}
?>
</tbody>
</table>
</div>
</div>
Have a look at the official documentation https://www.php.net/manual/en/mysqli-result.fetch-array.php
or here for a brief summary https://www.w3schools.com/php/func_mysqli_fetch_array.asp
The result of mysqli_fetch_array is a an array of array: a list of samples where each sample is a list of fields from the query table.

CSS Grid breakout for page title

I am using a css grid (previously been using flexbox) and I am trying to work out how to break out of a css grid for my page title. My site structure looks like this:
Here is the css:
.site {
column-gap: $sidebar-gap;
display: grid;
grid-template-columns: auto ($sidebar-width); // site structure
grid-template-rows: auto 1fr auto; // sticky header & footer
grid-template-areas:
"header header"
"main sidebar"
"footer footer";
}
header {
grid-area: header;
}
.site-main {
grid-area: main;
}
.widget-area {
grid-area: sidebar;
}
footer {
grid-area: footer;
}
My HTML structure looks like this:
body
└── div (#page .site)
├── header (#masthead .site-header)
| ├── div (.site-branding)
| | ├── a (.logo)
| | └── p (.site-description)
| ├── nav (#site-navigation .main-navigation)
| | ├── button (.menu-toggle)
| | ├── div (#menu-desktop-container .menu-desktop-container)
| | └── div (#menu-mobile-container .menu-mobile-container)
| └── div (.head-search)
|
├── main (#primary .site-main)
| └── article (.module)
| ├── div (.page-head)
| | ├── h1 (.page-title)
| | └── div (.page-meta)
| └── div (.page-content)
| └── <page content goes here>
|
├── aside (#secondary .widget-area)
| └── <content> (section)
|
└── footer (#colophon .site-footer)
├── div (.footer-widgets)
├── nav (.footer-navigation)
| └── div (#menu-footer-container .menu-footer-container)
└── div (.site-info)
What I am trying to achieve is the .page-head div to breakout of the css grid and span across the entire width of the page. From here I would like the sidebar (i.e. .widget-area) to commence below the .page-head. Typically in the past when using flexbox I would achieve this would using position: absolute on the .page-head which has a fixed height. I would then just add margin-top to the .widget-area to be the same as the .page-head site.
I tried this in CSS grid and this doesn't work. This is what I am trying to achieve visually:
I am not able to change the HTML structure - i.e. the obvious thing would be to move the sidebar (.widget-area) within main (.site-main), then this would be super easy to achieve. As this is a Wordpress theme, this is not possible.
You can do it with a grid inside a grid and this will do the job :
To be sure the layout meet your requirements I use the html of your codepen.
Test the snippet below :
.site {
column-gap: 40px;
display: grid;
grid-template-columns: auto (25%);
grid-template-rows: auto 3rem 1fr auto;
}
header {
grid-row: 1;
grid-column: 1 / 3;
}
.site-main {
grid-row: 2 / 4;
grid-column: 1 / 3;
}
.widget-area {
grid-row: 3;
grid-column: 2;
}
footer {
grid-row: 4;
grid-column: 1 / 3;
}
article {
display: grid;
column-gap: 40px;
grid-template-columns: auto (25%);
grid-template-rows: 3rem 1fr;
width: 100%;
height: 100%;
}
.page-head {
grid-column: 1 / 3;
grid-row: 1;
text-align: center;
}
.page-content {
grid-column: 1;
grid-row: 2;
}
.site {
padding: 0 10px;
}
header,
footer {
background-color: grey;
color: white;
padding: 50px 0;
text-align: center;
}
header {
margin-bottom: 40px;
}
footer {
margin-top: 40px;
}
.page-content {
border: 1px solid blue;
}
h1 {
border: 1px solid red;
margin: 0;
padding: 0;
}
.widget-area {
border: 1px solid green;
.module {
margin-bottom: 20px;
}
}
<div class="site">
<header>Header</header>
<main class="site-main">
<article class="module">
<div class="page-head">
<h1>Page Title</h1>
</div>
<div class="page-content">
</div>
</article>
</main>
<aside class="widget-area">
<div class="module">Widget 1</div>
<div class="module">Widget 2</div>
<div class="module">Widget 3</div>
</aside>
<footer>Footer</footer>
</div>
Or check the Codepen here : https://codepen.io/BSO__/pen/ZEXvgXR

Vue Component Unit Testing

I have a counter component - pretty straight forward.
<div> + </div>
<input type="text" v-model="countData" />
<div> - </div>
Detailed code is here - https://github.com/Shreerang/Vue-Nuggets/blob/master/src/components/QuantitySelector/QuantitySelector.vue
I am trying to unit test this component.
it('Renders a default quantity selector with the max count set to 6', () => {
const wrapper = shallowMount(QuantitySelector);
wrapper.find('input[type="text"]').setValue('1');
expect(wrapper.find('input[type="text"]').element.value).toBe('1'); // notice here that the value is a String, whereas I expect it to be a Number
wrapper.findAll('div').at(2).trigger('click');
expect(wrapper.vm.countData).toBe('2'); // This fails as countData becomes "11" instead of doing a 1 + 1 = 2 and then becoming Number 2.
expect(wrapper.find('input[type="text"]').element.value).toBe(2); // You can notice the same thing as above.
wrapper.find('input[type="text"]').setValue(wrapper.vm.countData); // Do I have to do this? This does not seem right to me :frowning:
});
I am not able to get this unit test to work! Any help with this is appreciated!
Text fields contain text values. Note that you even specified a text value: setValue('1'). If you change the value in the input manually, (say, to 3) and press the increment button, it becomes 31. Your test is telling you the truth.
You need to change your functions to convert to number. [Update] As your comment informed me, Vue has a .number modifier for v-model for this very purpose
new Vue({
el: '#app',
name: 'quantity-selector',
props: {
count: {
type: Number,
default: 1,
}, // Makes sense to have default product count value
maxCount: {
type: Number,
default: 6,
}, // maxCount makes sense when you have a restriction on the max quantity for a product
iconDimensions: {
type: Number,
default: 15,
},
minusIconFillColor: {
type: String,
default: '#000',
},
plusIconFillColor: {
type: String,
default: '#000',
},
isCountEditable: {
type: Boolean,
default: true,
},
},
data() {
return {
countData: this.count,
};
},
computed: {
minusIconColor: function() {
return this.countData === this.count ? '#CCC' : this.minusIconFillColor;
},
plusIconColor: function() {
return this.countData === this.maxCount ? '#CCC' : this.plusIconFillColor;
},
},
methods: {
decrement: function() {
if (this.countData > this.count) {
this.countData -= 1;
}
},
increment: function() {
if (this.countData < this.maxCount) {
this.countData += 1;
}
},
adjustCount: function() {
if (this.countData > this.maxCount) {
this.countData = this.maxCount;
} else if (this.countData < this.count) {
this.countData = this.count;
} else {
if (isNaN(Number(this.countData))) {
this.countData = this.count;
}
}
},
}
});
.nugget-quantity-counter {
display: inline-flex;
}
.nugget-quantity-counter div:first-child {
border: solid 1px #ccc;
border-radius: 5px 0px 0px 5px;
}
.nugget-quantity-counter div:nth-child(2) {
border-top: solid 1px #ccc;
border-bottom: solid 1px #ccc;
display: flex;
flex-direction: column;
justify-content: center;
}
.nugget-quantity-counter input[type='text'] {
border-top: solid 1px #ccc;
border-bottom: solid 1px #ccc;
border-left: none;
border-right: none;
text-align: center;
width: 20px;
padding: 12px;
margin: 0;
font-size: 16px;
}
.nugget-quantity-counter div:last-child {
border: solid 1px #ccc;
border-radius: 0px 5px 5px 0px;
}
.nugget-quantity-counter > div {
cursor: pointer;
padding: 12px;
width: 20px;
text-align: center;
}
.nugget-quantity-counter > div > svg {
height: 100%;
}
<script src="https://unpkg.com/vue#latest/dist/vue.js"></script>
<div id="app">
<div #click="decrement">
<svg viewBox="0 0 24 24" :width="iconDimensions" :height="iconDimensions">
<g>
<path d='M64 0 M2 11 L2 13 L22 13 L22 11 Z' :fill="minusIconColor" />
</g>
</svg>
</div>
<input v-if="isCountEditable" type="text" v-model.number="countData" #blur="adjustCount" />
<div v-else>{{countData}}</div>
<div #click="increment">
<svg viewBox="0 0 24 24" :width="iconDimensions" :height="iconDimensions">
<g>
<path d="M 11 2 L 11 11 L 2 11 L 2 13 L 11 13 L 11 22 L 13 22 L 13 13 L 22 13 L 22 11 L 13 11 L 13 2 Z" :fill="plusIconColor" />
</g>
</svg>
</div>
</div>

PHP - preg_replace and str_replace only replace only once inside foreach

I have a foreach that uses a Glob function in order to get some .htm files and finally put that content in one echo.
I Tried to replace one specific phrase located in all this .htm files with some data that I extract from the each .htm filename.
So,
$juzgado_radicado generates a number like ---> 004
$year_radicado generates a number like ---> 2015
$radicado_radicado generates a number like ---> 00911
That numbers are changing depending of foreach iteration getting a new file name.
But at the end I use preg_replace or str_replace in order to change a phrase inside the each .htm document but instead replacing the numbers in each iteration I only get the same result in all replaces. So I get something like "00911" in all .htm files and it have to be something like "00911" and "00577" por example.
I don't know why preg_replace and str_replace have this behaviour inside the foreach loop.
$directory2 = "/Applications/XAMPP/xamppfiles/htdocs/tecnojuridica/finalizado/";
$array_filename = glob($directory2 . "*.htm");
$string = '';
foreach($array_filename as $filename)
{
$xml_file = file_get_contents($filename, FILE_TEXT);
preg_match('/[0-9]{23}/', $filename, $match);
$radicado = $match[0];
// 002
$juzgado_radicado = substr($radicado, -14, 3);
// 2015
$year_radicado = substr($radicado, -11, 4);
// 00958
$radicado_radicado = substr($filename, -7, 5);
// Dom Object
$dom = new DOMDocument('1.0', 'utf-8');
$dom->xmlStandalone = true;
$dom->loadHTML($xml_file);
$content_node = $dom->getElementById("divrandom");
$mega = $dom->saveXML($content_node);
$string2 = preg_replace('/Datos del Proceso/', ' <font size="30"> <span style="background-color: #73A6FF; color: #fff; display: inline-block; padding: 3px 10px; font-weight: bold; border-radius: 5px;">' . $juzgado_radicado . '</span> <span style="background-color: #73A6FF; color: #fff; display: inline-block; padding: 3px 10px; font-weight: bold; border-radius: 5px;">' . $year_radicado . '</span> <span style="background-color: #73A6FF; color: #fff; display: inline-block; padding: 3px 10px; font-weight: bold; border-radius: 5px;">' . $radicado_radicado . ' </span> </font>', $mega);
$string.= $mega . ',';
}
echo utf8_decode($string2);
Thanks in advance.
I've found the Answer: You have to replace at star of the foreach loop not with Php Dom Document Objects.
If you tried to make replacement into Dom Objects it's possible that fails because str_replace of preg_replace can't make all iterations with different replace data.

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