Reputation: 257
I have a row of four images, each image has some text below. For mobile screens, since each image will be smaller, I want the text to disappear and make one line instead that has some dynamic text so this text will change depending on the image that is active (clicked), meaning I now will show the text only if the image is clicked. How can I achieve this? I have the following so far:
.grid {
display: flex;
flex-wrap: wrap;
margin: 0 auto;
max-width: 1300px;
}
.grid__col {
padding-right: 16px
padding-left: 16px;
}
.icons-grid {
img {margin: 0 auto;}
}
.icon-text {
max-width: 200px;
margin: 0 auto;
}
@media (min-width:961px) {
.grid__col--1-4-l {
width: 25%;
}
}
@media (min-width:641px) {
.grid__col--1-4-m {
width: 25%;
}
}
.grid__col--1-4-s {
width:25%;
}
.grid_col--end {
margin-left: auto;
}
<div class="grid icons-grid ">
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text1' data-text='Text 1'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 1</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text2' data-text='Text 2'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 2</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text3' data-text='Text3'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 3</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s grid__col--end text4' data-text='Te 4'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 4</p>
</div>
</div>
Upvotes: 0
Views: 140
Reputation: 142
You can accomplish this with simple jquery.
$('.grid__col').on('click',function(e){
var text = $(this).data('text');
$(this).find('p').text(text);
});
.grid {
display: flex;
flex-wrap: wrap;
margin: 0 auto;
max-width: 1300px;
}
.grid__col {
padding-right: 16px
padding-left: 16px;
}
.icons-grid {
img {margin: 0 auto;}
}
.icon-text {
max-width: 200px;
margin: 0 auto;
}
@media (min-width:961px) {
.grid__col--1-4-l {
width: 25%;
}
}
@media (min-width:641px) {
.grid__col--1-4-m {
width: 25%;
}
}
.grid__col--1-4-s {
width:25%;
}
.grid_col--end {
margin-left: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="grid icons-grid ">
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text1' data-text='Text 1'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text"></p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text2' data-text='Text 2'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text"></p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text3' data-text='Text3'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text"></p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s grid__col--end text4' data-text='Text 4'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text"></p>
</div>
</div>
Upvotes: 0
Reputation: 175
You could achieve that without the use of JS.
Place a transparent checkbox (opacity: 0) as the first child of every .grid__col
(Before the image) with the exact same size of the image and then add the following css:
.grid__col > input:nth-child(1) {
width: 140px !important;
height: 100px !important;
position: absolute !important;
opacity: 0 !important;
}
.grid__col > input:nth-child(1):checked+img+.icon-text {
visibility: visible !important;
display: block !important;
}
.grid__col > input:nth-child(1)
is to assure that the desired input (checkbox) is a child and the first child with the tagname input
of .grid__col
so the style we want for the trasparent checkbox goes there.
.grid__col > input:nth-child(1):checked+img+.icon-text
is to tell the browser that if my desired checkbox
is checked
then apply the style to an element with a class name .icon-text
that is adjacent to an element img
that is a also adjacent to the checked checkbox
.
.grid {
display: flex;
flex-wrap: wrap;
margin: 0 auto;
max-width: 1300px;
}
.grid__col {
padding-right: 16px
padding-left: 16px;
}
.icons-grid {
img {margin: 0 auto;}
}
.icon-text {
max-width: 200px;
margin: 0 auto;
visibility: hidden;
display: none;
}
@media (min-width:961px) {
.grid__col--1-4-l {
width: 25%;
}
}
@media (min-width:641px) {
.grid__col--1-4-m {
width: 25%;
}
}
.grid__col--1-4-s {
width:25%;
}
.grid_col--end {
margin-left: auto;
}
.grid__col > input:nth-child(1) {
width: 140px !important;
height: 100px !important;
position: absolute !important;
opacity: 0 !important;
}
.grid__col > input:nth-child(1):checked+img+.icon-text {
visibility: visible !important;
display: block !important;
}
<div class="grid icons-grid ">
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text1' data-text='Text 1'>
<input type="checkbox"/>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 1</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text2' data-text='Text 2'>
<input type="checkbox"/>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 2</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text3' data-text='Text3'>
<input type="checkbox"/>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 3</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s grid__col--end text4' data-text='Te 4'>
<input type="checkbox"/>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 4</p>
</div>
</div>
EDIT
Lets say that you want a single .icon-text
to appear (That the other ones disappear when you click another image).
if you want to do that with the same technique, then the only thing you have to do is to change the type of the input
to radio
and link them with a name "show-text" or something else.
<input type="checkbox"/>
to <input type="radio" name="show-text"/>
. There is no need to change the css.
.grid {
display: flex;
flex-wrap: wrap;
margin: 0 auto;
max-width: 1300px;
}
.grid__col {
padding-right: 16px
padding-left: 16px;
}
.icons-grid {
img {margin: 0 auto;}
}
.icon-text {
max-width: 200px;
margin: 0 auto;
visibility: hidden;
display: none;
}
@media (min-width:961px) {
.grid__col--1-4-l {
width: 25%;
}
}
@media (min-width:641px) {
.grid__col--1-4-m {
width: 25%;
}
}
.grid__col--1-4-s {
width:25%;
}
.grid_col--end {
margin-left: auto;
}
.grid__col > input:nth-child(1) {
width: 140px !important;
height: 100px !important;
position: absolute !important;
opacity: 0 !important;
}
.grid__col > input:nth-child(1):checked+img+.icon-text {
visibility: visible !important;
display: block !important;
}
<div class="grid icons-grid ">
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text1' data-text='Text 1'>
<input type="radio" name="show-text"/>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 1</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text2' data-text='Text 2'>
<input type="radio" name="show-text"/>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 2</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text3' data-text='Text3'>
<input type="radio" name="show-text"/>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 3</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s grid__col--end text4' data-text='Te 4'>
<input type="radio" name="show-text"/>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 4</p>
</div>
</div>
Upvotes: 1
Reputation: 10141
Here is the working DEMO
Here is the JS code:
$(function() {
//for mobile do this
//Hide icon text on page load
$('p.icon-text').hide();
//On image click toggle display icon text
$('img').click(function() {
//alert('clicked');
$(this).siblings('p.icon-text').toggle();
});
})
Upvotes: 0
Reputation: 1635
js is obviously more efficient here but you can also do this with pure CSS.
Set .icon-text {display: none}
on small screens
Then, using the Adjacent sibling selector you can target the specific .icon-text
after each img to display it when the image is clicked or active
basic example at 641px cut off:
.grid {
display: flex;
flex-wrap: wrap;
margin: 0 auto;
max-width: 1300px;
}
.grid__col {
padding-right: 16px padding-left: 16px;
}
img {
margin: 0 auto;
border: 1px solid red;
}
.icon-text {
max-width: 200px;
margin: 0 auto;
}
@media (min-width:961px) {
.grid__col--1-4-l {
width: 25%;
}
}
@media (min-width:641px) {
.grid__col--1-4-m {
width: 25%;
}
}
.grid__col--1-4-s {
width: 25%;
}
.grid_col--end {
margin-left: auto;
}
@media (max-width: 641px) {
.icon-text {
display: none;
}
img:active+.icon-text,
img:hover+.icon-text,
img:focus+.icon-text {
display: inline-block;
max-width: 100vw;
margin: 0 auto;
background: #131418;
color: white;
width: auto;
padding: 10px 0;
}
}
<div class="grid icons-grid ">
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text1' data-text='Text 1'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 1</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text2' data-text='Text 2'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 2</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text3' data-text='Text3'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 3</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s grid__col--end text4' data-text='Te 4'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 4</p>
</div>
</div>
Upvotes: 1
Reputation: 3730
With JavaScript, you can do
event.target.nextElementSibling.style.display = 'block';
fired on click of the image, to display the adjacent text.
Or you can toggle the display:
element.style.display = element.style.display === 'block' ? 'none' : 'block'; //element would be event.target.nextElementSibling
var images = document.getElementsByTagName("img");
for (var i=0, len=images.length, img; i<len; i++) {
img = images[i];
img.addEventListener("click", function(event) {
var image = event.target.nextElementSibling;
image.style.display = image.style.display === 'block' ? 'none' : 'block';
});
}
.grid {
display: flex;
flex-wrap: wrap;
margin: 0 auto;
max-width: 1300px;
}
.grid__col {
padding-right: 16px
padding-left: 16px;
}
.icons-grid {
img {margin: 0 auto;}
}
.icon-text {
max-width: 200px;
margin: 0 auto;
display: none;
}
@media (min-width:961px) {
.grid__col--1-4-l {
width: 25%;
}
}
@media (min-width:641px) {
.grid__col--1-4-m {
width: 25%;
}
}
.grid__col--1-4-s {
width:25%;
}
.grid_col--end {
margin-left: auto;
}
<div class="grid icons-grid ">
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text1' data-text='Text 1'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 1</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text2' data-text='Text 2'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 2</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s text3' data-text='Text3'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 3</p>
</div>
<div class='grid__col grid__col--1-4-l grid__col--1-4-m grid__col--1-4-s grid__col--end text4' data-text='Te 4'>
<img src='http://via.placeholder.com/140x100'>
<p class="icon-text">Text 4</p>
</div>
</div>
Upvotes: 0
Reputation: 575
The simplest way to do that would probably be to hide the multiple of texts using media-queries, just as you did in your code (only use max-width:641px
and modify the display
parameter).
Aside from that, add a separate p
, with an opposite media-query that shows it only for the wider displays, and in javascript dynamically control its value.
const outputNode = document.querySelector('.icon-text--mobile');
const gridNodes = document.querySelectorAll('.grid__col');
const gridNodesArray = Array.prototype.slice.call(imageNodes);
gridNodesArray.forEach(function (node, index) {
const nodeImage = node.querySelector('img');
const nodeText = node.querySelector('p').innerText;
nodeImage.addEventListener('click', function () {
outputNode.innerText = nodeText;
});
});
Upvotes: 0