Search code examples
javascripthtmlcssdropdownsinatra

Responsive dropdown menu in CSS


I'm trying to implement a dropdown menu in CSS. It's pretty much done, but I need the items which are below the dropdown to move down so there's room for the dropdown items. And when I close the dropdown menu, I want the items to go up again just as they were before the dropdown was shown.

Here's the code I used:

function toggleDropdown(id) {
  var dropdown = document.getElementById(id);
  dropdown.style.display = dropdown.style.display === 'block' ? 'none' : 'block';
}

document.addEventListener('click', function(event) {
  var dropdown = document.getElementById('introduccion-dropdown');
  var trigger = document.querySelector('.dropdown');
  if (!trigger.contains(event.target)) {
    dropdown.style.display = 'none';
  }
});
@import url('font-sets.css');
@import url('common.css');

/* Styles for the dropdown menu */

* {
    list-style: none;
}

.dropdown-content {
    display: none;
    position: absolute;
    min-width: 160px;
    z-index: 1;
    top: 70%;
    left: 50%;
    transform: translate(-50%, -50%);
    left: 49%;
}
  
.dropdown-content li {
    display: block;
}

.items-below-dropdown {
    position: relative;
    margin-top: 400px; /* Adjust the value based on the height of the dropdown menu */
}

/* Styles for the lesson and test cards */

.button-stack {
    margin-top: 20px;
    display: flex;
    flex-direction: column;
    align-items: center;
}
  
.card {
    background-color: var(--primary-color);
    color: var(--text-color);
    position: relative;
    width: 700px;
    height: 113px;
    border-radius: 15px;
    border: none;
    box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
    font-size: 24px;
    display: flex;
    justify-content: center;
    align-items: center;
    margin-bottom: 20px;
    cursor: pointer;
    transition: transform 0.2s;
}

.card:hover {
    transform: scale(1.15);
}

.card::before {
    content: "";
    position: absolute;
    top: 10%;
    bottom: 10%;
    left: 20%;
    transform: translateX(-50%);
    width: 2px;
    background-color: var(--text-color);
}

.card .number, 
.card .letter {
    position: absolute;
    top: 50%;
    left: 10%;
    transform: translate(-50%, -50%);
    font-size: 48px;
    font-weight: bold;
}

.card-content {
    width: 55%;
    padding: 0 20px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
}
  
.card-title {
    font-size: 25px;
    font-weight: bold;
    margin-bottom: 10px;
}
  
.card-subtitle {
    font-size: 18px;
    color: var(--text-color);
}
  
.lesson-card {
    width: 600px;
    height: 90px;
    background: var(--primary-color);
    color: var(--text-color);
}
  
.test-card {
    width: 600px;
    height: 90px;
    background: var(--accent-color);
    color: var(--text-color);
}
<div class="button-stack">
  <li class="dropdown">
    <button type="submit" class="card" onclick="toggleDropdown('introduction-dropdown')">
      <div class="card-content">
        <h2 class="card-title">Introduccion a Haskell</h2>
      </div>
      <div class="card-divider"></div>
      <span class="letter">1</span>
    </button>
      <ul class="dropdown-content" id="introduction-dropdown">
        <li>
          <form action="/home" method="post">
            <input type="hidden" name="lesson_id" value="1">
            <button type="submit" class="card lesson-card">
              <div class="card-content">
                <h2 class="card-title">Titulo de leccion</h2>
              </div>
              <div class="card-divider"></div>
              <span class="number">1.1</span>
            </button>
          </form>
        </li>
        <li>
          <form action="/home" method="post">
            <input type="hidden" name="lesson_id" value="1">
            <button type="submit" class="card lesson-card">
              <div class="card-content">
                <h2 class="card-title">Titulo de leccion</h2>
              </div>
              <div class="card-divider"></div>
              <span class="number">1.2</span>
            </button>
          </form>
        </li>
        <li>
          <form action="/home" method="post">
            <input type="hidden" name="lesson_id" value="1">
            <button type="submit" class="card lesson-card">
              <div class="card-content">
                <h2 class="card-title">Titulo de leccion</h2>
              </div>
              <div class="card-divider"></div>
              <span class="number">1.3</span>
            </button>
          </form>
        </li>
        <li>
          <form action="/home" method="post">
            <input type="hidden" name="test_id" value="1">
            <button type="submit" class="card test-card">
              <div class="card-content">
                <h2 class="card-title">Test</h2>
                <h3 class="card-subtitle">Temas del test</h3>
              </div>
              <div class="card-divider"></div>
              <span class="letter">1.A</span>
            </button>
          </form>
        </li>
      </ul>  
  </li>
  <div class="items-below-dropdown">
    <li>
      <button type="submit" class="card">
        <div class="card-content">
          <h2 class="card-title">Funciones</h2>
        </div>
        <div class="card-divider"></div>
        <span class="letter">2</span>
      </button>
    </li>
    <li>
      <button type="submit" class="card">
        <div class="card-content">
          <h2 class="card-title">Monadas</h2>
        </div>
        <div class="card-divider"></div>
        <span class="letter">3</span>
      </button>
    </li>
    <li>
      <button type="submit" class="card">
        <div class="card-content">
          <h2 class="card-title">Functores</h2>
        </div>
        <div class="card-divider"></div>
        <span class="letter">4</span>
      </button>
    </li>
  </div>  
</div>

I tried changing the margin-top attribute, but that only moves the items down, no matter if I press the dropdown button or not. I need something that can respond when the dropdown button is pressed. Maybe is a JS function, but I'm no expert at JavaScript


Solution

  • Try this. I just removed all the position: absolute stuff and that big margin-top. Nothing was added, I only commented out a few lines of CSS, which I marked with /*COMMENTED OUT*/ so it's easy to find.

    function toggleDropdown(id) {
      var dropdown = document.getElementById(id);
      dropdown.style.display = dropdown.style.display === 'block' ? 'none' : 'block';
    }
    
    document.addEventListener('click', function(event) {
      var dropdown = document.getElementById('introduccion-dropdown');
      var trigger = document.querySelector('.dropdown');
      if (!trigger.contains(event.target)) {
        dropdown.style.display = 'none';
      }
    });
    @import url('font-sets.css');
    @import url('common.css');
    
    /* Styles for the dropdown menu */
    
    * {
        list-style: none;
    }
    
    .dropdown-content {
        display: none;
        
        /*COMMENTED OUT*/
        /*position: absolute;*/
        
        min-width: 160px;
        z-index: 1;
        
        /*COMMENTED OUT*/
        /*top: 70%;
        left: 50%;
        transform: translate(-50%, -50%);
        left: 49%;*/
    }
      
    .dropdown-content li {
        display: block;
    }
    
    .items-below-dropdown {
        position: relative;
        
        /*COMMENTED OUT*/
        /*margin-top: 400px;*/ /* Adjust the value based on the height of the dropdown menu */
    }
    
    /* Styles for the lesson and test cards */
    
    .button-stack {
        margin-top: 20px;
        display: flex;
        flex-direction: column;
        align-items: center;
    }
      
    .card {
        background-color: var(--primary-color);
        color: var(--text-color);
        position: relative;
        width: 700px;
        height: 113px;
        border-radius: 15px;
        border: none;
        box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
        font-size: 24px;
        display: flex;
        justify-content: center;
        align-items: center;
        margin-bottom: 20px;
        cursor: pointer;
        transition: transform 0.2s;
    }
    
    .card:hover {
        transform: scale(1.15);
    }
    
    .card::before {
        content: "";
        position: absolute;
        top: 10%;
        bottom: 10%;
        left: 20%;
        transform: translateX(-50%);
        width: 2px;
        background-color: var(--text-color);
    }
    
    .card .number, 
    .card .letter {
    
        /*COMMENTED OUT*/
        /*position: absolute;
        top: 50%;
        left: 10%;
        transform: translate(-50%, -50%);*/
        font-size: 48px;
        font-weight: bold;
    }
    
    .card-content {
        width: 55%;
        padding: 0 20px;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: flex-start;
    }
      
    .card-title {
        font-size: 25px;
        font-weight: bold;
        margin-bottom: 10px;
    }
      
    .card-subtitle {
        font-size: 18px;
        color: var(--text-color);
    }
      
    .lesson-card {
        width: 600px;
        height: 90px;
        background: var(--primary-color);
        color: var(--text-color);
    }
      
    .test-card {
        width: 600px;
        height: 90px;
        background: var(--accent-color);
        color: var(--text-color);
    }
    <div class="button-stack">
      <li class="dropdown">
        <button type="submit" class="card" onclick="toggleDropdown('introduction-dropdown')">
          <div class="card-content">
            <h2 class="card-title">Introduccion a Haskell</h2>
          </div>
          <div class="card-divider"></div>
          <span class="letter">1</span>
        </button>
          <ul class="dropdown-content" id="introduction-dropdown">
            <li>
              <form action="/home" method="post">
                <input type="hidden" name="lesson_id" value="1">
                <button type="submit" class="card lesson-card">
                  <div class="card-content">
                    <h2 class="card-title">Titulo de leccion</h2>
                  </div>
                  <div class="card-divider"></div>
                  <span class="number">1.1</span>
                </button>
              </form>
            </li>
            <li>
              <form action="/home" method="post">
                <input type="hidden" name="lesson_id" value="1">
                <button type="submit" class="card lesson-card">
                  <div class="card-content">
                    <h2 class="card-title">Titulo de leccion</h2>
                  </div>
                  <div class="card-divider"></div>
                  <span class="number">1.2</span>
                </button>
              </form>
            </li>
            <li>
              <form action="/home" method="post">
                <input type="hidden" name="lesson_id" value="1">
                <button type="submit" class="card lesson-card">
                  <div class="card-content">
                    <h2 class="card-title">Titulo de leccion</h2>
                  </div>
                  <div class="card-divider"></div>
                  <span class="number">1.3</span>
                </button>
              </form>
            </li>
            <li>
              <form action="/home" method="post">
                <input type="hidden" name="test_id" value="1">
                <button type="submit" class="card test-card">
                  <div class="card-content">
                    <h2 class="card-title">Test</h2>
                    <h3 class="card-subtitle">Temas del test</h3>
                  </div>
                  <div class="card-divider"></div>
                  <span class="letter">1.A</span>
                </button>
              </form>
            </li>
          </ul>  
      </li>
      <div class="items-below-dropdown">
        <li>
          <button type="submit" class="card">
            <div class="card-content">
              <h2 class="card-title">Funciones</h2>
            </div>
            <div class="card-divider"></div>
            <span class="letter">2</span>
          </button>
        </li>
        <li>
          <button type="submit" class="card">
            <div class="card-content">
              <h2 class="card-title">Monadas</h2>
            </div>
            <div class="card-divider"></div>
            <span class="letter">3</span>
          </button>
        </li>
        <li>
          <button type="submit" class="card">
            <div class="card-content">
              <h2 class="card-title">Functores</h2>
            </div>
            <div class="card-divider"></div>
            <span class="letter">4</span>
          </button>
        </li>
      </div>  
    </div>