John R
John R

Reputation: 257

Make a dynamic text change when clicking an image

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

Answers (6)

Amit Arya
Amit Arya

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

MarioE
MarioE

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

Rahul Gupta
Rahul Gupta

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

I haz kode
I haz kode

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

Chava Geldzahler
Chava Geldzahler

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

Maciek Jurczyk
Maciek Jurczyk

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

Related Questions