What is the best method for utilizing the CSS :target selector in order to generate a versatile modal box?

I am looking for a way to display my vast collection of proverbs from an endangered language without overcrowding the page. I have implemented a modal box solution using CSS :target selector, which expands a hidden div element when clicked on. However, I need this functionality to work for each individual proverb without having to create unique classes or IDs for each one. Currently, only the first div box expands when a proverb is clicked in the middle of the list. Is there a way to achieve this for all proverbs without creating hundreds of unique expandable divs?

Below is the code snippet I have been using:

#modalBox {
  display: block;
  position: relative;
  text-align: left;
  overflow: hidden;
  background: #ffffff;
  transition: all 0.4s;
  padding: 5px;
  margin-bottom: 2rem;
  height: 2.5rem;
  width: 100%;
  max-width: 800px;
}

#modalBox:target {
  height: 13.5rem;
}
<div class="proverbs">
  <div id="modalBox">
    <a href="#modalBox"> A (g)attë mbrèšarolë facë i (g)attarièddë cëcatë.</a>
    <p id="data"><b>IPA:</b> a atːə mˌbɾɪʃəˈɾolə fat͡ʃ i ˈatːaɾiˌɛdːə t͡ʃə katʰ</p>
    <p id="data"><b>Italian:</b> La gatta frettolosa fa i gattini ciechi.</p>
    <p id="data"><b>English:</b> The hasty cat makes blind kittens.</p>
    </p>
    <a href="#" class="modalclose">&times;</a>
  </div>
</div>

Answer №1

To create this effect, there are numerous CSS-first methods that don't heavily rely on Javascript.

Surprisingly, one approach doesn't even heavily depend on CSS; it's an HTML-first solution.

Using the details / summary elements provide excellent semantic markup for displaying this type of information.


Here is a functional example:

.modalBox {
  display: block;
  position: relative;
  width: min(98%, 800px);
  padding: 5px;
  overflow: hidden;
}

.modalBox summary {
  font-style: italic;
  cursor: pointer;
}

.modalBox p {
  transform: translateY(30vh);
  transition: transform 0.3s linear;
}

.modalBox[open] p {
  transform: translateY(0);
}
<div class="proverbs">
  <details class="modalBox">
    <summary> A (g)attë mbrèšarolë facë i (g)attarièddë cëcatë.</summary>
    <p data-lang="ipa"><b>IPA:</b> a atːə mˌbɾɪʃəˈɾolə fat͡ʃ i ˈatːaɾiˌɛdːə t͡ʃə katʰ</p>
    <p data-lang="it"><b>Italian:</b> La gatta frettolosa fa i gattini ciechi.</p>
    <p data-lang="en"><b>English:</b> The hasty cat makes blind kittens.</p>
  </details>
  
  <details class="modalBox">
    <summary> A (g)attë mbrèšarolë facë i (g)attarièddë cëcatë.</summary>
    <p data-lang="ipa"><b>IPA:</b> a atːə mˌbɾɪʃəˈɾolə fat͡ʃ i ˈatːaɾiˌɛdːə t͡ʃə katʰ</p>
    <p data-lang="it"><b>Italian:</b> La gatta frettolosa fa i gattini ciechi.</p>
    <p data-lang="en"><b>English:</b> The hasty cat makes blind kittens.</p>
  </details>
  
  <details class="modalBox">
    <summary> A (g)attë mbrèšarolë facë i (g)attarièddë cëcatë.</summary>
    <p data-lang="ipa"><b>IPA:</b> a atːə mˌbɾɪʃəˈɾolə fat͡ʃ i ˈatːaɾiˌɛdːə t͡ʃə katʰ</p>
    <p data-lang="it"><b>Italian:</b> La gatta frettolosa fa i gattini ciechi.</p>
    <p data-lang="en"><b>English:</b> The hasty cat makes blind kittens.</p>
  </details>
</div>


For more information:

Answer №2

Featuring over 100 proverbs that require JavaScript functionality. In this scenario, an array of objects is utilized to populate the content upon user interaction with either the #next or #back buttons. The data itself is the only element that needs modification:

const proverbs = [
  {
    main: `A (g)attë mbrèšarolë facë i (g)attarièddë cëcatë.`,
    ipa: `a atːə mˌbɾɪʃəˈɾolə fat͡ʃ i ˈatːaɾiˌɛdːə t͡ʃə katʰ`,
    it: `La gatta frettolosa fa i gattini ciechi.`,
    en: `The hasty cat makes blind kittens.`
  },...
];
/*
Data structure follows [{main: 'first line', ipa: 'line of IPA notation', it: 'Italian translation',
 en: 'English translation'}, {second proverb}, {third proverb},...]
*/

While the utilization of #id is due to the preference of the HTMLFormElement interface which accepts references based on #id, [name], or index -- #id was chosen as it simplifies CSS selector writing. With a single modal catering to an endless list of compact proverbs, using #id should not pose any issues, and in case they do, the [name] attribute can be utilized instead.

Further details are elaborated within the example code comments

// Referencing <form>
const UI = document.forms.UI;
// Array comprising proverbs and translations
const proverbs = [
  {main: `A (g)attë mbrèšarolë facë i (g)attarièddë cëcatë.`,
   ipa: `a atːə mˌbɾɪʃəˈɾolə fat͡ʃ i ˈatːaɾiˌɛdːə t͡ʃə katʰ`,
   it: `La gatta frettolosa fa i gattini ciechi.`,
   en: `The hasty cat makes blind kittens.`},
   {main: `010101010101010101010101010101010101010101`, ipa: `02`, it: `03`, en: `04`},
   {main: `1111111111111111111111111111111111111111111111111`, ipa: `12`, it: `13`, en: `14`},
   {main: `2121212121212121212121212121212121212121212121`, ipa: `22`, it: `23`, en: `24`},
   {main: `3131313131313131313131313131313131313131313131`, ipa: `32`, it: `33`, en: `34`},
   {main: `4141414141414141414141414141414141414141414141`, ipa: `42`, it: `43`, en: `44`},
   {main: `5151515151515151515151515151515151515151515151`, ipa: `52`, it: `53`, en: `54`}
];
// Counter definition
let count = 0; 
// Binding <form> to click event
UI.onclick = clickHandler;
// Click event handler automatically passes Event Object
function clickHandler(e) {
  // Referencing <dialog>
  const modal = document.querySelector('.proverbs');
  // Identifying what the user clicked
  const clk = e.target;
  // Referring all <button>s and <fieldset>
  const IO = this.elements;
  // Opening <dialog> if #open is clicked
  if (clk.matches('#open')) {
    clk.style.display = 'none';
    modal.showModal();
  }
  // Closing <dialog> if #close is clicked
  if (clk.matches('#close')) {
    IO.open.style.display = 'inline-flex';
    modal.close();
  }
  /*
  Upon clicking #next...
  ...increase counter...
  ...if counter exceeds length of proverbs array...
  ...reset counter to 0 (starting again)...
  ...call move() with updated count and IO references
  */
  if (clk.matches('#next')) {
    ++count;
    if (count > (proverbs.length-1)) count = 0;
    move(count, IO);
  }
  // Following similar logic for #back button
  if (clk.matches('#back')) {
    --count;
    if (count < 0) count = proverbs.length -1;
    move(count, IO);
  }
}
// Passing counter and form control reference (IO) 
function move(i, fc) {
  // Referencing <ul>
  const list = document.querySelector('.list');
  // New content string for <legend>
  const main = `<legend>${proverbs[i].main}</legend>`;
  // String for content of <ul>
  const items = `
        <li><b>IPA: </b>${proverbs[i].ipa}</li>
        <li><b>Italian: </b>${proverbs[i].it}</li>
        <li><b>English: </b>${proverbs[i].en}</li>`;
  // Clearing existing <legend> and <li>
  fc.content.firstElementChild.remove();
  list.replaceChildren();
  // Inserting new htmlStrings
  fc.content.insertAdjacentHTML('afterbegin', main);
  list.insertAdjacentHTML('beforeend', items);
}
@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@300&family=Raleway:wght@500&display=swap');

html {
  font: 500 2ch/1.2 'Oswald'
}

dialog {
  position: relative;
  padding-top: 25px;
  border-radius: 8px;
  box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, 
              rgba(0, 0, 0, 0.23) 0px 3px 6px;
}

#content {
  border-radius: 4px;
}

legend {
  font-family: 'Raleway';
  font-weight: 900;
  margin-bottom: -8px;
}

#close {
  position: absolute;
  right: 4px;
  top: 4px;
  height: 1rem;
  font-size: 1.2rem;
}

ul {
  margin-left: 0px;
}

li {
  margin-bottom: 8px;
}

button {
  display: inline-flex;
  align-items: center;
  border: 2px outset rgb(227, 227, 227);
  border-radius: 4px;
  font: inherit;
  font-variant: small-caps;
  cursor: pointer;
}

.btn {
  float: right;
}

#back {
  border-top-left-radius: 4px;
  border-bottom-left-radius: 4px;
  border-top-right-radius: 0px;
  border-bottom-right-radius: 0px;
}

#next {
  border-top-left-radius: 0px;
  border-bottom-left-radius: 0px;
  border-top-right-radius: 4px;
  border-bottom-right-radius: 4px;
}
<form id='UI'>
  <button id='open' type='button'>Open</button>
  <dialog class="proverbs">
    <button id="close" type='button'>&times;</button>
    <fieldset id='content'>
      <legend>A (g)attë mbrèšarolë facë i (g)attarièddë cëcatë.</legend>
      <ul class='list'>
        <li><b>IPA: </b>a atːə mˌbɾɪʃəˈɾolə fat͡ʃ i ˈatːaɾiˌɛdːə t͡ʃə katʰ</li>
        <li><b>Italian: </b>La gatta frettolosa fa i gattini ciechi.</li>
        <li><b>English: </b>The hasty cat makes blind kittens.</li>
      </ul>
      <button id='next' class='btn' type='button'>Next</button>
      <button id='back' class='btn' type='button'>Back</button>
    </fieldset>
  </dialog>
</form>

Answer №3

If you're looking for a cleaner way to achieve this without relying heavily on JavaScript, I have a vanilla approach that might interest you. Instead of directly targeting specific ids, we can utilize class names and allow the browser to determine which clicked element corresponds to which id.

This JavaScript solution dynamically assigns incremental ids (e.g., modalBox0, modalBox1, etc.) to each modal box div and generates corresponding links (e.g., href='#modalBox0', href='#modalBox1', etc.).

const modals = document.querySelectorAll('.modalBox');

modals.forEach((modal, index) => {
  const id = `modalBox${index}`;
  modal.id = id
  const link = modal.querySelector('a');
  link.setAttribute('href', `#${id}`)
})
.modalBox {
  display: block;
  position: relative;
  text-align: left;
  overflow: hidden;
  background: #ffffff;
  transition: all 0.4s;
  padding: 5px;
  margin-bottom: 2rem;
  height: 2.5rem;
  width: 100%;
  max-width: 800px;
}

.modalBox:target {
  height: 13.5rem;
}
<div class="proverbs">
  <div class="modalBox">
    <a href="#"> A (g)attë mbrèšarolë facë i (g)attarièddë cëcatë.</a>
    <p id="data"><b>IPA:</b> a atːə mˌbɾɪʃəˈɾolə fat͡ʃ i ˈatːaɾiˌɛdːə t͡ʃə katʰ</p>
    <p id="data"><b>Italian:</b> La gatta frettolosa fa i gattini ciechi.</p>
    <p id="data"><b>English:</b> The hasty cat makes blind kittens.</p>
    <a href="#" class="modalclose">&times;</a>
  </div>

  <div class="modalBox">
    <a href="#"> A (g)attë mbrèšarolë facë i (g)attarièddë cëcatë.</a>
    <p id="data"><b>IPA:</b> a atːə mˌbɾɪʃəˈɾolə fat͡ʃ i ˈatːaɾiˌɛdːə t͡ʃə katʰ</p>
    <p id="data"><b>Italian:</b> La gatta frettolosa fa i gattini ciechi.</p>
    <p id="data"><b>English:</b> The hasty cat makes blind kittens.</p>
    <a href="#" class="modalclose">&times;</a>
  </div>
</div>

Check out the jsFiddle here

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring JavaFX and FXML TreeTableView customization for column and header styles

I've been working on a JavaFX project and I'm having trouble customizing the style of the TreeTableView header or columns, like changing the color, width, font size, etc. I've tried using various codes like these but none seem to work. ...

Begin the animation again by hitting the start button, using the burst-engine and canvas

I have successfully created a simple animation using Burst Engine and HTML5. My goal is to make the start button trigger the animation to restart if pressed twice. Currently, when I press it, the animation just starts and nothing else happens. I suspect t ...

Selection determines the value of two fields

This form has predefined values that are used to create a link, but the issue is that these values vary depending on the location. Can you assist me with this problem? <input type="radio" id="iconapp1" name="department" value="1250"/><label for ...

Python code encountering issues within Django framework

I'm having trouble showing and hiding HTML elements based on the data I receive after clicking a button. The output of another Python file will generate this data, but the if statement doesn't seem to be working as expected: {% if data == 'e ...

How to create a full-page background image using Bootstrap?

Take a look at this example: In the provided example, there is a background landing page that expands to fit the width of the viewport, remains responsive, and does not take up the full width of the page. How can you utilize bootstrap to manually code an ...

How to send PHP email using HTML form

After attempting to find an answer to my inquiry here, I am now starting a new thread. Just a brief explanation: I have a Contact Form with 180 input fields and calculations for each field. I wish to send all the fields along with the calculated values v ...

What is the best way to maintain the formatting of a textarea in the database?

My HTML form includes a text area and a functionality to save the data into a database upon submission. The issue arises when the saved data is retrieved from the database, as the original formatting of the text gets altered. For instance: "This is a text ...

centered text positioned perfectly on a dynamically adjusting background

Seeking help to center text both vertically and horizontally within a circle background link that needs to be responsive. Setting the line-height equal to the height of the link is not an option, here's my code: html <a class="Previous" href="#"& ...

The z-index overlapping problem in webkit browsers is a result of Angular 7 animations

I have implemented staggered animations in my Angular 7 application to bring elements to life upon page load. However, I am facing a strange z-index problem with one of my components. Here is the animation code: @Component({ selector: 'track-page& ...

The MUI makeStyles() class has been implemented, yet the styles are not being displayed when using classList.add('class-name')

Currently, I am utilizing MUI makeStyles() to create a series of CSS classes. Within these classes, I am dynamically including and excluding one specific class to my Box element during file drag-and-drop events. The class is successfully added, as I can o ...

Having trouble integrating the css and js animation files into my Django project

settings.py import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SECRET_KEY = '@6qt%i+0&_=z0#zl^+!u3bw6c7dmg4e3khboj%7s7439z9#ky(' DEBUG = True ALLOWED_HOSTS = [] INSTALLED_APPS = [ 'django.contrib.admin& ...

Create stunning HTML emails by incorporating a transparent background color behind images and text

Is there a way to add text on a transparent background layer placed over an image without using the background-image property? In my case, I am working on an HTML Emailer and must utilize the img tag instead. Any suggestions on how to achieve this? < ...

React - Obtain User Login Details and Verify

I am working on a React project that includes a Login Form. The code has been organized into small components for reusability, but I am unsure of how to retrieve and validate user credentials (username and password). Is there a method available to validate ...

Utilizing conditional statements for confirming purchased orders with a pop-up confirmation box

function purchaseClicked() { var orders = prompt("Are you sure you want to buy these Items?"); if (orders != null) { alert('Please try selecting your items again!') } else { alert('Thank you for shopping ...

The entire image is unable to be shown within the div

When adding images to a carousel, I encountered an issue where only the top half of the image is displayed on the page. It seems that the image is not adjusting itself to fit the div container properly, resulting in only a portion of it being visible behin ...

Pictures change positions in online email interfaces like gmail

Hey there! I'm encountering an issue with the image on my website. The image is contained within a container and seems to extend a bit to the right. Everything looks perfect in all email clients except for web-based ones like Hotmail and Gmail. Here a ...

Convert JSON data from jQuery into a modal form within a div element

I am currently working on an MVC application and attempting to populate a bootstrap modal form with data from the server. My approach involves: 1) Loading a grid with various IDs, each linked to a javascript onclick function. 2) The function retrieves th ...

I am facing an issue with properly linking my jQuery

After searching through numerous posts on this website, I have yet to find a solution to my problem. My issue involves trying to implement a simple jQuery function that is not functioning as expected. It appears that the jQuery link may not be properly set ...

I am curious if there is a wysiwyg web editor extension specifically designed for VS2010 available?

In my experience, I have been working with C#, HTML coding using VS2010 and MVC. Utilizing VS2010 has proven to be an invaluable tool for me in this process. Currently, I find myself needing to create some straightforward static web pages. I am wondering ...

The styling for buttons links is malfunctioning

I am currently developing my own version of Bootstrap and focusing on buttons and links. I have anchor tags within the button element, but the link styling is not displaying correctly. HTML <button class="btn-danger"><a href="#">Danger</a& ...