Is there a solution for overflow indicators in combination with a FlexBox column layout?

To clarify this question, we do not have to provide a CSS-only solution. We are open to using JavaScript in our data-driven project.


Hello! Thank you for visiting.

In summary, we want to enhance Flexbox column layout by breaking the content at specific points with what we call "Overflow Indicators".

Check this out:

https://i.sstatic.net/SDTyV.png

I've tried some examples of this concept, but I am more of a UX Designer than a developer, see here: (am I close?)

https://codepen.io/cclark413/pen/XvxbqV

var detectWrap = function(className) {
  
  var wrappedItems = [];
  var prevItem = {};
  var currItem = {};
  var items = document.getElementsByClassName(className);

  for (var i = 0; i < items.length; i++) {
    currItem = items[i].getBoundingClientRect();
    if (prevItem && prevItem.top > currItem.top) {
      wrappedItems.push(items[i]);
    }
    prevItem = currItem;
  };
  
  return wrappedItems;

}

window.onload = function(event){
  var wrappedItems = detectWrap('block');
  for (var k = 0; k < wrappedItems.length; k++) {
    wrappedItems[k].classList.add("wrapped")
    wrappedItems[k].innerText= "I wrapped!"
  }
};
* {
  box-sizing:border-box;
  font-family:sans-serif;
}
div.container {
  padding:15px 0;
  background-color:black;
  display: flex;
  flex-direction: column;
  align-content: flex-start;
  flex-wrap: wrap;
  width:1024px;
  height:400px;
  margin:0 auto;
}  
div.container > div {
  margin:0 15px;
  width:33.3%;
}
.header, .footer {
  padding:5px;
  background-color:#333;
  color:white;
  text-transform:uppercase;
  font-size:10px;
}
.item {
  background-color:#e1e1e1;
  padding:15px;
}
div.spacer {
  background-color:transparent !important;
  height:15px;
}
div.wrapped {
  color:white;
  background-color: red;
}
<div class="container">
  <div class="header block">
    <div class="row">
      Row 1 Header
    </div>
    <div class="row">
      Row 2 Header
    </div>
  </div>
  <div class="item block">Item 1</div>
  <div class="item block">Item 2</div>
  <div class="item block">Item 3</div>
  <div class="footer block">Test</div>
  <div class="spacer block"></div>
  <div class="header block">Header 2</div>
  <div class="item block">Item 1</div>
  <div class="item block">Item 2</div>
  <div class="item block">Item 3</div>
  <div class="item block">Item 4</div>
  <div class="item block">Item 5</div>
  <div class="footer block">Test</div>
</div>

However, I have encountered a small issue with this solution: - The content is treated individually within the container instead of as "Coagulated Panels," limiting our ability to make changes to the panel itself. We need to find a way to encase the individual panel content after they have been split for overflow. Currently, I separated everything to utilize native flex capabilities.

While Flexbox gets us halfway there, it lacks the intelligence to fully utilize flex content. We aim to complicate things further by introducing Overflow Indicators (Jagged edges that mimic a torn panel starting a new column).

Here are some guidelines:

  • This is a web interface utilizing Angular, HTML, CSS.
  • The header/footer should always be connected. The header should accompany item one, and the footer should pair with the last item. Breaking panels in any other way is acceptable.
  • We seek an elegant solution for the jagged edge, allowing customization with various background colors to match the panel's states (Disabled, Active, Cancelled, etc). We prefer a non-image based solution, possibly leveraging a versatile SVG.
  • Although we want the content to overflow the page with pagination, we still desire the option of implementing horizontal scrolling for future panel views.

It might be an assumption that Flexbox is the ideal answer here rather than another solution. Excited to see innovative solutions!

Answer №1

When it comes to creating a multi-column layout in CSS, the CSS Multi-Column Layout Module is the way to go (not to be confused with flex-box). This module is designed to achieve exactly what you are looking for and is reasonably well supported.

However, there are a few things to keep in mind:

  1. The CSS handles the column flow automatically, so it may not provide indicators when content crosses columns. I am still investigating this aspect.

  2. The web was not originally designed with "pagination" in mind, so splitting content into multiple column containers may pose challenges. One workaround could involve adding more columns and allowing the container to scroll instead.

Example of Columns

.columns {
margin: 30px;
columns: 3;
}

.item {
    padding: 4px;
    background: #ddd;
}

header, 
footer, 
li {
display:block;
padding: 20px;
margin: 0;
background: #333;
color: #eee;
}
footer {
margin-bottom: 10px;
}

ul {
margin: 0;
padding: 0;
}

li {
list-style: none;
border-bottom: 1px solid #ddd;
background: #eee;
color: #333;
}

header, 
footer, 
ul>li:first-child, 
ul>li:last-child {
-webkit-column-break-inside: avoid;
          page-break-inside: avoid;
               break-inside: avoid;
}
<div class="columns">

<div class="items">
<!-- using a list to so :first/:last child work -->
        <!-- probably don't even need the "items" wrapper but it makes everthing a bit cleaner -->
<header>Header</header>
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
<footer>Footer</footer>
</div>


<div class="items">
<header>Header</header>
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
<footer>Footer</footer>
</div>

<div class="items">
<header>Header</header>
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
<footer>Footer</footer>
</div>

<div class="items">
<header>Header</header>
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
<footer>Footer</footer>
</div>

</div>

Edit:

Enhancing Pagination with Pseudo-elements

I have been exploring ways to improve the column split indicators by utilizing pseudo-elements positioned behind the next/previous elements. However, there are certain issues such as the Column container behaving as if it has overflow: hidden, without any override option (a known bug). A potential solution involves creating a local stacking context using techniques like will-change, although this approach has its own set of challenges.

You can track my progress on this matter through my CodePen project.

Answer №2

To incorporate that design using flexbox, a clever trick is required. It involves adding a pseudo-element with a lower z-index and an ornament background to achieve the desired effect. All items will then align like tiles on a house roof. An example has been created with lower triangles, but the same technique can be applied for upper ornaments as well. It's worth noting that for top ornaments, there are still some open questions (the ::before pseudo-class was attempted, but z-index didn't work for it).

Here is a live working example showcasing the lower ornament implementation: https://codepen.io/emankovski/pen/jONWgpy

https://i.sstatic.net/7l59B.png

CSS:


.flex-container {
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column;
  -webkit-flex-wrap: wrap;
  -ms-flex-wrap: wrap;
  flex-wrap: wrap;
  -webkit-justify-content: flex-start;
  -ms-flex-pack: start;
  justify-content: flex-start;
  -webkit-align-content: stretch;
  -ms-flex-line-pack: stretch;
  align-content: stretch;
  -webkit-align-items: stretch;
  -ms-flex-align: stretch;
  align-items: stretch;
  height: 180px;
  background-color: #000;
}

.flex-item {
  -webkit-order: 0;
  -ms-flex-order: 0;
  order: 0;
  -webkit-flex: 0 1 auto;
  -ms-flex: 0 1 auto;
  flex: 0 1 auto;
  -webkit-align-self: auto;
  -ms-flex-item-align: auto;
  align-self: auto;
  margin-left: 5px;
}

.header,
.footer {
  background-color: #333;
  color: white;
  text-transform: uppercase;
  font-size: 10px;
  padding: 15px;
}
.header {
  margin-top:-5px;
}
.footer {
  z-index: 5;

  transform: translate(0px, -5px);
}

.item {
  padding-top: 5px;
  background-color: #e1e1e1;
  z-index: 5;
}

.item:after {
  display: inline-block;
  height: 5px;
  content: " ";
  width: 100%;
  z-index: 4;
  transform: translate(0px, 8px);
  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAYAAADA+m62AAAAQElEQVQoU2N8+PDhfwYiACO6Qnl5eQwxkDkogiBFMMPRDYArRFaETTFYITZF6IrhVuHzD8gwohSCPUNEyICVAADpLCXVkRgaFQAAAABJRU5ErkJggg==)
    repeat;
}

.spacer {
  background-color: transparent;
  height: 10px;
}

HTML:

<div class="flex-container">

  <div class="item flex-item panel-1">
    <div class="header">Header 1
    </div>Item 1</div>
  <div class="item flex-item panel-1">Item 2</div>
  <div class="item flex-item panel-1">Item 3</div>
  <div class="flex-item ">
    <div class="item panel-1">Item 4</div>
    <div class="footer">Footer</div>
    <div class="spacer"></div>
  </div>
  <div class="item flex-item panel-1">
    <div class="header">Header 1
    </div>Item 1</div>
  <div class="item flex-item panel-1">Item 2</div>
  <div class="item flex-item panel-1">Item 3</div>
  <div class="item flex-item panel-1">Item 4</div>
  <div class="item flex-item panel-1">Item 5</div>
  <div class="item flex-item panel-1">Item 6</div>
  <div class="item flex-item panel-1">Item 7</div>
  <div class="flex-item ">
    <div class="item panel-1">Item 8</div>
    <div class="footer">Footer</div>
    <div class="spacer"></div>
  </div>
</div>

A pattern generator from was used to create the background pattern.

https://i.sstatic.net/NDA5Z.png

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

group items into ranges based on property of objects

I've been grappling with this issue for far too long. Can anyone provide guidance on how to tackle the following scenario using JavaScript? The dataset consists of objects representing a date and a specific length. I need to transform this list into a ...

The authorization header for jwt is absent

Once the user is logged in, a jwt token is assigned to them. Then, my middleware attempts to validate the token by retrieving the authorization header, but it does not exist. When I try to display the request header by printing it out, it shows as undefine ...

What is the proper way to assign a class name to an animation state in Angular 2/4?

I am currently working with Angular Animations using version 4.1.3 Check out the code snippet below: @Component({ selector : 'my-fader', animations: [ trigger('visibilityChanged', [ state('true' , style({ opaci ...

Is it necessary for CSS Media query to load all the referenced CSS files?

When utilizing a CSS Media Query to assign two different stylesheets, such as desktop.css and mobile.css based on the max-width, how does this process function? Is it necessary for both stylesheets to be loaded by the browser every time, and then the appr ...

The Javascript function will keep on executing long after it has been invoked

I am currently facing an issue with calling a JavaScript function within an AJAX call. The progress function below is supposed to be executed every time the for loop runs. However, the problem is that although progress is being run as many times as the for ...

Is there a way to dynamically change select2 styling using code when a form is submitted?

Having trouble highlighting empty select2 selects when a form is submitted? I'm struggling to override my existing CSS styling upon document load. Check out my jQuery attempt: var $requiredUnfilledItems = $(".required:not(.filled)"); if ($requiredUn ...

Is it possible to style a nested ID with CSS?

Imagine a scenario where you are working within an HTML file that you cannot modify, but you have the ability to only edit the CSS through a stylesheet. Is it possible to target an ID within another ID in the same way you can do with classes? #id1 #id2 {s ...

What could be causing my screen reader to repeat lines?

I have this HTML structure: <button ng-disabled="vm.updating" ng-click="doSomething()" class="something" type="submit" aria-label="average score"> <span ng hide="hideConditional()" class="font-white">score</span> <span ng-show= ...

Converting POST data into an array using Angular

I am facing an issue with my post request setup in a NodeJS app. The data sent returns as an array, but I am struggling to convert it into the desired format. My Angular code is structured as follows: newWord = ''; keyword = ''; onCli ...

Node.js (Express), passport.js, mongoose.js, and Android app all have in common the HTTP Error 307 - Temporary redirect

I am currently constructing a REST Api using Node.js (Express.js and Moongose.js). I have a single post route that takes JSON data and redirects it to the signup page (/app/signup) if the user is a first-time user (not found in the database), or to the log ...

html<script src="" and causing a redirect when button is clicked

My login.html page for logging in can be found in the design folder. <html> <head> <title>Login Page</title> <script src="../Script/login.js"> </script> </head> <body> <h3> Login</h3> ...

Is there a way to copy this JavaScript variable and modify the displayed text?

I am working on a JavaScript code that is used to create a basic news page with a filter from a mySQL database. The code generates the heading, main content, and date created for each news item. I now need to add a "read more" link at the bottom of each ne ...

Tips for disabling automatic browser scrolling to a specific div ID?

I have a webpage with a vertical accordion in the center to display content. Upon loading the page, the accordion is centered. However, when a user clicks on a tab, the entire page scrolls up, moving the tab to the top of the browser. Is there a way to pre ...

Width of flex container overflowing from relative position is at its full capacity

I'm attempting to create a horizontal line across an overflowing flex container by using an absolutely positioned child element with both the left and right set to 0. This requires the container to have a relative position to contain the absolutely po ...

Problem with CSS Styling: Classes are intended to have consistent appearance but appear quite distinct

Can someone help me understand why the input fields for my username and password are displaying at different sizes, even though they are styled together in my CSS file? I'm still new to this and just experimenting, but I can't figure out what&apo ...

The spacing within the table's <tr> elements does not get altered

I am struggling to add a small space in the table <tr> but my attempts have not been successful. How can I resolve this issue? Please refer to the image below for clarification: https://i.sstatic.net/HXdhq.png .panel-booking .panel-body { pad ...

What is the best way to include a background image in an Angular selector?

I'm having trouble setting a background image for an Angular selector. Here's the code I'm using: <app-highway-card [ngStyle]="{'background-image':'url(https://cdn.pixabay.com/photo/2021/09/04/09/32/road-6597404__340.j ...

What is the reason behind the failure of next/script with Google reCAPTCHA?

Currently, I am in the process of upgrading from next js version 8 to version 11. I wanted to take advantage of the amazing next js feature for "next/script". However, when I tried to implement it for Google reCAPTCHA using "react-recaptcha": "^2.3.10", th ...

Is it possible to continuously increase the value of a CSS property with each click?

I am trying to implement a feature where the value of an element decreases each time a different element is clicked. Currently, I have the following code: $("#trigger_heritage").click(function () { $(".heritage_content ul").css("margin-left", + -880); ...

How come my directive is being updated when there are changes in a different instance of the same directive?

For the purpose of enabling Angular binding to work, I developed a straightforward directive wrapper around the HTML file input. Below is the code for my directive: angular.module('myApp').directive('inputFile', InputFileDirective); f ...