Dynamic Sizing of Elements + Adaptive Text Overlay

There were 2 obstacles I encountered when trying to create an image-based drop-down menu :

  1. No matter how much effort I put in, I couldn't figure out how to make a flexed element inside a container maintain the same height as the adjacent element. [In my jsFiddle example, each slideout content revealed by hover should match the height of the icons.]

  2. I struggled to place text over each image due to the menu resizing itself based on device width - which is necessary and cannot be compromised. The solutions I found all involved using position:absolute, but I couldn't get it to work. [Ideally, there would be labels on top of each image.]

Feel free to ask for clarifications if needed.

Check out the example in this jsFiddle link. Thank you.

Answer №1

To enhance clarity and promote code reusability, the CSS has been segmented into four primary sections:

  • Globals, which define page defaults and override standard HTML/CSS values
  • Mechanism section for Flexbox Layout settings and element sizing/actions
  • Eye-candy generics focusing on spacing, fonts, and borders for visual appeal
  • Eye-candy theming for color-related features utilizing a custom attribute [theme="gr-blue"], with options for additional themes

Flexbox Layout Tips

To align the .slideout-content to the left or right, you can employ the row-reverse direction and justify-content: flex-end for an odd .menu-item, while using the default row direction for an even one.

Image Text Overlay Strategy

This technique utilizes relative and absolute positioning of parent and child elements respectively. The overlay text is extracted from the data-overlay custom attribute within the child content.

Notable Changes/Warnings

  • The code includes detailed comments and offers alternative applications of the Flexbox Layout.
  • An adjustment was made due to compatibility issues in IE11 with filter: brightness(1.2); consider suitable alternatives.
  • The transparency/opacity of .slideout-content has been slightly modified to showcase hover effects.
  • Viewport-based sizes were implemented where applicable.
  • A strategic shift was made from using child margin to parent padding, particularly crucial when combining relative sizes ('%') with box-sizing: border-box.
  • Opt for flex-grow: 1 instead of flex: 1 to ensure compatibility with IE11.
  • Experiment by changing dir="ltr" to dir="rtl" within the <body> tag to assess document reading order adjustments.

Cross-Browser Testing

The layout has been verified to function seamlessly across Chrome/Edge, Firefox, and IE11 at a minimum screen size of 320x480px without requiring scrolling.

Further Updates

UPDATE 1: Mentioned removal of original footer {...height: 5vh...} as it may lead to overflow issues below the footer

UPDATE 2: Updated CSS rules to position overlay .slideout::after correctly within its parent container for improved alignment. For more insights on this topic, refer to w3schools: CSS Layout - Horizontal & Vertical Align.

Answer №2

To ensure that the content of the menu-top stretches, you must set its display property to flex. Additionally, for the overlay on the image to work correctly, you need the position: absolute rule along with one of the positioning rules such as top right bottom left declared, and its parent element should have a relative position. I've implemented a flexbox-based solution based on your description. Instead of using columns, I made the children wrap at 50%, and used :nth-child(odd) to style the odd children with order: 1 or order: 2 rules to position the menu on the left or right side, accordingly. I also included a .page__wrap class on a div to wrap the entire page, including the header, main content, and footer, allowing them to flex so that the footer remains at the bottom even without scrolling.

body {
  margin: 0;
}

.page__wrap {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

header {
  background-color: lightgray;
  border-bottom: 5px solid gray;
}

h2 {
  text-align: center;
  margin: 0;
  padding: 2em 0;
}

main {
  flex: 1;
}

footer {
  background-color: gold;
  padding: 1em 0;
  justify-self: flex-end;
}

.slideouts__wrapper {
  display: flex;
  flex-wrap: wrap;
  max-width: 65rem;
  margin: 0 auto;
}

.slideout {
  display: flex;
  margin: 10px;
  width: calc(50% - 20px);
  justify-content: flex-start;
}

.slideout:nth-child(odd) {
  justify-content: flex-end;
}

.slideout__avatar {
  background-color: red;
  flex: 0 1 auto;
  object-fit: cover;
  position: relative;
}

.slideout__avatar--image {
  display: block;
  width: 100%
}

.slideout__avatar--overlay {
  position: absolute;
  bottom: 0;
  width: 100%;
  background-color: #00000095;
  color: white;
  transition: .2s;
  display: flex;
  justify-content: center;
  align-items: center;
}

.slideout:nth-child(odd) .slideout__avatar {
  order: 2;
  position: relative;
}

.slideout__menu {
  display: flex;
  flex: 0 0 50%;
}

.slideout__menu--items {
  display: none;
  flex-direction: column;
  justify-content: stretch;
  margin: 0;
  padding: 0;
  flex: 1;
  list-style: none;
  background-color: #736E6F;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  padding: 1%;
}

.slideout__menu--item {
  flex: 1;
  display: flex;
  border: thin inset #888585;
    border-radius: 5%;
}

.slideout__menu--item:hover {
  filter: brightness(1.2);
}

.slideout__menu--item--anchor {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  text-decoration: none;
    color: goldenrod;
}

.slideout__avatar:hover + .slideout__menu .slideout__menu--items {
  display: flex;
}

.slideout__avatar:hover .slideout__avatar--overlay {
  opacity: 1;
}

.slideout__menu--items:hover {
  display: flex;
}
<div class="page__wrap">
  <header>
    <div class="header__container">
      <h2>links of links</h2>
    </div>
  </header>
  <main class="slideouts__container">
    <div class="slideouts__wrapper">
      <div class="slideout">
        <div class="slideout__avatar">
          <img class="slideout__avatar--image" src="https://avatarfiles.alphacoders.com/105/thumb-105223.jpg" alt="scale">
          <div class="slideout__avatar--overlay">
            <p>the overlay</p>
          </div>
        </div>
        <div class="slideout__menu">
          <ul class="slideout__menu--items">
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 1</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 2</a></li>
          </ul>
        </div>
      </div>
      <div class="slideout">
        <div class="slideout__avatar">
          <img class="slideout__avatar--image" src="https://avatarfiles.alphacoders.com/105/thumb-105223.jpg" alt="scale">
          <div class="slideout__avatar--overlay">
            <p>the overlay</p>
          </div>
        </div>
        <div class="slideout__menu">
          <ul class="slideout__menu--items">
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 1</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 2</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 3</a></li>
          </ul>
        </div>
      </div>
      <div class="slideout">
        <div class="slideout__avatar">
          <img class="slideout__avatar--image" src="https://avatarfiles.alphacoders.com/105/thumb-105223.jpg" alt="scale">
          <div class="slideout__avatar--overlay">
            <p>the overlay</p>
          </div>
        </div>
        <div class="slideout__menu">
          <ul class="slideout__menu--items">
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 1</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 2</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 3</a></li>
          </ul>
        </div>
      </div>
      <div class="slideout">
        <div class="slideout__avatar">
          <img class="slideout__avatar--image" src="https://avatarfiles.alphacoders.com/105/thumb-105223.jpg" alt="scale">
          <div class="slideout__avatar--overlay">
            <p>the overlay</p>
          </div>
        </div>
        <div class="slideout__menu">
          <ul class="slideout__menu--items">
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 1</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 2</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 3</a></li>
            <li class="slideout__menu--item"><a class="slideout__menu--item--anchor" href="#">link 4</a></li>
          </ul>
        </div>
      </div>
      
    </div>
  </main>
  <footer>
    <div class="footer__container">
      <p>footer text</p>
    </div>
  </footer>
</div>

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

Input field that adjusts its width based on screen size, accompanied by two buttons displayed side

I need a solution to display a text input and two buttons side by side. The buttons should take up only the space they require, while the text input should expand to fill the remaining space. It's important to have small margins between these elements ...

Transform a list of H1..6 into a hierarchical structure

I have a task to convert H1 to H6 tags from a markdown file into a JavaScript hierarchy for use in a Table of Contents. The current list is generated by AstroJS and follows this format [{depth: 1, text: 'I am a H1'}, {depth: 2: 'I am a H2}] ...

Guide to importing a Kotlin/JS generated module into a separate npm-dependent project

I am interested in developing a JavaScript library using Kotlin Multiplatform (such as the project found here, which includes a websocket server and a JavaScript client). My goal is to build this library as an npm package and then import it into my Vue pro ...

Adding a class to a clicked button in Vue.js

A unique function of the code below is showcasing various products by brand. When a user clicks on a brand's button, it will display the corresponding products. This feature works seamlessly; however, I have implemented a filter on the brands' lo ...

Unable to get HTML text input validation with RegEx to function, despite incorporating the required attribute

I am attempting to create dynamically generated text inputs that only allow for digits and an optional decimal point. I have added the required attribute but the inputs are not responding to the RegEx pattern. var howMuch = $("<input>").attr("type", ...

Unable to use column formatting on a row using flexbox

I am working on creating a layout with rows and columns where the content in each column is vertically aligned. Here is an example of what I am trying to achieve: Currently, I am using react and have multiple components. The approach I believe will work ...

Issue with QuickSand Script not displaying properly on Internet Explorer 7

My website features an edited version of Quicksand that displays correctly on Chrome, Opera, and Firefox, but runs into CSS issues on IE. Oddly enough, when I was using the static version, the CSS displayed properly even on IE until I added the Quicksand e ...

Graph is not showing up when navigating through page

On my List page (List.Html), users can select multiple rows to display the data in a chart using C3. However, when clicking on the compareList() button to navigate to the Chart page (Chart.Html), the chart does not display properly. It seems that the chart ...

The shadows in Three Js are functioning correctly, although there are a few shadow lines visible below my model

I am currently in the process of modifying a three.js scene, despite having little experience with javascript and three.js. After successfully adding a shadow to my GLTF model, I noticed some yellow and red lines beneath the model that I cannot identify or ...

The filtering and sorting features of Ng-table do not seem to be working properly when dealing with grouped data

Currently, I am in the process of learning angular.js and have recently started using the ng-table directive. While I have successfully managed to group my data and display it using ng-table, I seem to be facing issues with sorting and filtering the data. ...

Make changes to the HTML file by directly using Jquery or JavaScript

Allow me to elaborate on my current objective. I have an HTML file that requires direct content updates. Specifically, I am working with elements sharing the 'id=test'. My goal is to dynamically update all elements with unique IDs such as ' ...

Vue failing to update when a computed prop changes

As I work with the Vue composition API in one of my components, I encountered an issue where a component doesn't display the correct rendered value when a computed property changes. Strangely, when I directly pass the prop to the component's rend ...

Tips for featuring the latest blog post at the top of a NextJS blog

I have a website built on Next JS with a blog page. The setup is correct, where the /blog page displays content based on slugs. Currently, new blog posts are appearing at the bottom of the page, under older ones. I want to reverse this so that when a new p ...

Angular applications can redirect to their own internal pages when linking to an external URL

I've recently started using Angular and have encountered a minor issue. My routing setup is working as expected in the navbar, but I have a link that points to an external URL. When I click on it, instead of redirecting me to the external site, it ta ...

A New Approach to Initializing Web Pages in ASP.NET (with a Surprising Twist)

Well, I've encountered quite the puzzling issue with a project I'm working on (it could even make it to the Daily WTF), and I'm hoping for some help in finding a solution. (Apologies in advance for the lengthy explanation...) About a month ...

Utilizing media queries and page width in a Moodle theme designed with Bootstrap framework

I currently have my LMS set up with Moodle 4 and the boost theme which is based on bootstrap (github) However, the default page layout appears very narrow on all devices and I would like to utilize the responsive design features of Bootstrap for different ...

Is there a way to eliminate the default Tab indicator in Materializecss?

Utilizing the tab feature in MaterializeCSS to enhance the navigation tabs for my web application. By default, the initial tab is already chosen, evident by the underlined indicator beneath it as depicted in the image below. https://i.sstatic.net/PbGb5.pn ...

Update your mappings for the city of Istanbul when utilizing both TypeScript and Babel

Currently, I am facing the challenge of generating code coverage for my TypeScript project using remap Istanbul. The issue arises due to the usage of async/await in my code, which TypeScript cannot transpile into ES5 directly. To circumvent this limitation ...

When the browser is resized, the fadeIn() function restarts from the

My plan was to create a dynamic effect where a browser-sized div would rotate through 3 different backgrounds using jQuery's fading effect. However, I encountered an issue - whenever I resize the browser window, the effect restarts from the beginning ...

Navigating to the following webpage with Selenium using Python

url_main = "https://comic.naver.com/webtoon/detail.nhn?titleId=131385&no=292" This particular website features a comment pagination at the bottom of the page. Upon inspecting the page, I noticed that the buttons were structured like this: &l ...