Creating CSS boxes in a dual column layout with a step-by-step approach

Currently, I am in the process of developing a user interface for a menu that looks something like this:

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

I am exploring different implementation methods for this design. In this project, I am utilizing Bootstrap framework. The main container is a container-fluid from Bootstrap nested inside another DIV that occupies 50% width of the screen. This is why I opted for container-fluid, considering its fluid nature.

I can leverage Bootstrap (version 3) Grid's functionality (col-xx-x), or any other CSS techniques to accomplish this layout.

So far, here is what I have achieved using float: left:

* {
  box-sizing: border-box;
}

.container-fluid {
  margin-top: 75px;
}

.menu-items {
  padding: 0;
  position: relative;
  list-style-type: none;
  text-align: center;
}

.menu-item {
  display: inline-block;
  float: left;
  width: 50%;
  height: 250px;
}

.menu-item:nth-child(odd) {
  margin-top: -65px;
}
.menu-item:nth-child(even) {
  margin-top: 95px;
}

.image-wrapper{
  display: inline-block;
}

.image {
  background-color: gray;
  width: 80px;
  height: 100px;
}
<div class="container-fluid">
  <ul class="menu-items">
    <li class="menu-item">
      <div class="image-wrapper">
        <div class="image"></div>
      </div>
      <div class="text-wrapper">
        <span>Item 1</span>
      </div>
    </li>
    <li class="menu-item">
      <div class="image-wrapper">
        <div class="image"></div>
      </div>
      <div class="text-wrapper">
        <span>Item 2</span>
      </div>
    </li>
    <li class="menu-item">
      <div class="image-wrapper">
        <div class="image"></div>
      </div>
      <div class="text-wrapper">
        <span>Item 3</span>
      </div>
    </li>
    <li class="menu-item">
      <div class="image-wrapper">
        <div class="image"></div>
      </div>
      <div class="text-wrapper">
        <span>Item 4</span>
      </div>
    </li>
  </ul>
</div>

Answer №1

To achieve the desired layout using only CSS, you can utilize the properties float and clear, along with adding appropriate margin values to your elements. Here is a demonstration:

.container:after {
  content: "";
  display: table;
  clear: both;
}

.a,
.c {
  float: left;
}

.c {
  margin-top: 10px;
}

.b,
.d {
  float: right;
  margin-top: -30px;
}

.clear {
  clear: both;
}

/* additional styles for demonstration */
.container {
  background-color: #e0e0e0;
  padding: 30px;
}

/* additional styles for demonstration */
.item {
  background-color: orange;
  font-size: 2em;
  color: white;
  padding: 10px;
}
<div class="container">
  <div class="item a">One</div>
  <br class="clear" />
  <div class="item b">Two</div>
  <br class="clear" />
  <div class="item c">Three</div>
  <br class="clear" />
  <div class="item d">Four</div>
  <br class="clear" />
</div>

Answer №2

If you're adamant about using a solely CSS solution, consider employing floats and relative width units or percentages.

Below is a straightforward structure that doesn't rely heavily on code or frameworks like Bootstrap.

  1. Enclose the entire configuration within a div with the class "wrapper"
  2. Subsequently...group every two elements with the class "square" in a horizontal row specified by the class "row"
  3. Then...utilize nth-of-type selectors to adjust offsets accordingly, based on whether the element is the first or second one inside the "row" div.

Each "row" div will consistently occupy an entire line

All elements within the "row" are limited to 50% maximum width...resize your screen to see the effect.

See the Functional Demo:

* {
  box-sizing: border-box;
}

body {
  background: grey
}

.wrapper {
  width: 100%;
  margin: 12% auto;
}

img {
  display: block;
  max-width: 100%;
}

.square {
  background: black;
  width: 49%;
  text-align: center;
  display: inline-block;
  color:white;
}

.row {
  display: block;
  width: 80%;
  margin:0 auto;

}

.row .square:nth-of-type(1) {
  float: left;
}

.row:not(:nth-of-type(1)) .square:nth-of-type(1) {
  margin-top: 12%;
}

.row .square:nth-of-type(2) {
  margin-top: 12%;
  float: right;
}
<div class="wrapper">
  <div class="row">
    <div class="square"><img src="http://via.placeholder.com/1000x1000?text=one">Line for element 1</div>
    <div class="square"><img src="http://via.placeholder.com/1000x1000?text=two">Line for element 2</div>
  </div>
  <div class="row">
    <div class="square"><img src="http://via.placeholder.com/1000x1000?text=three">Line for element 3</div>
    <div class="square"><img src="http://via.placeholder.com/1000x1000?text=four">Line for element 4</div>
  </div>
</div>


This presents my method of utilizing pure CSS for this task.

However, here's how I would prefer to approach it.

I'd opt to integrate Masonry into the project. Despite its possible limitations for this specific use case, it significantly enhances design versatility.

[...] a JavaScript grid layout library. It works by placing elements in optimal position based on available vertical space, sort of like a mason fitting stones in a wall. You’ve probably seen it in use all over the Internet.

I understand your preference to avoid external libraries, but...

You can implement Masonry without jQuery:

Masonry v3 supports vanilla JS, without requiring jQuery.

Additionally, the minified library size is under 8kb, accessible at:

https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="640905170b0a161d4908051d0b111024504a564a54">[email protected]</a>/dist/masonry.pkgd.min.js

Considering this, utilizing Masonry might be beneficial.

Furthermore, you can initiate Masonry through HTML alone. For example:

<div class="grid" data-masonry='{ "itemSelector": ".grid-item", "columnWidth": 200 }'> 

Following these steps should yield the following outcome...

Note: (images may load slowly)

* {
  box-sizing: border-box;
}

body {
  text-align: center;
  background: #131418;
}

.grid {
  max-width: 100%;
  margin: 0 auto;
  width: 95vw;
}

.grid-item {
  width: 50%;
  background: white;
  border: 2px #131418 solid;
}

.grid-item img {
  width: 100%;
  height: auto;
}

.grid-item p {
  font-size: 16px;
  padding: 2px 15px;
  text-align: justify
}
<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>

<div class="grid" data-masonry='{ "itemSelector": ".grid-item"}'>
  <div class="grid-item"><img src="//unsplash.it/501/501" />
    <p>Lorem ipsum dolor sit amet, et equidem suscipit delicata eos. Simul scribentur delicatissimi te eam. Ius ea ullum dolorum disputando, pri putent definitiones et. Eos odio deleniti euripidis te, mea ex iudico praesent, et vix accusata percipitur. Ei
      nec quod lorem constituto. Eius intellegebat ad vis. Erat adipiscing conclusionemque mea at, omnesque cotidieque per ea. Oblique philosophia eos id, vel causae appellantur dissentiunt ad. Utroque corpora his an, suas ullamcorper nam ut. Nec iuvaret
      facilisi definiebas ea, ad omnium utamur ius.</p>
  </div>

  <div class="grid-item"><img src="//unsplash.it/511/511" />
    <p>Lorem ipsum dolor sit amet, sit prima oporteat ad, ad ridens tamquam his. Docendi platonem mea te, inani mentitum eum cu, in lorem eripuit debitis eum. Nam ei novum causae cotidieque, placerat similique at per, no his stet ferri animal. An option
      omittam invidunt vim. Dico aperiam cum te, his ei dicit civibus praesent, sed no salutandi hendrerit. Eam te inani verterem honestatis, id sit choro utroque pertinax. Sit cibo duis laoreet et, ea adhuc aliquam eum, mea paulo nostrum atomorum eu.
      Amet habeo semper ex vix, qui ea quas minimum. His at diam quaestio, ut hinc vocent principes eum. Ius sint movet labitur ea, per ad dignissim efficiendi. Idque assum vix at, diceret bonorum impedit eum ei, eos an duis decore deleniti. Duo dictas
      conceptam te.</p>
  </div>

  // Additional grid items go here

</div>

For another illustration featuring generic placeholders, where each item spans 50% width and boasts dynamic height, refer below. This variant also features the vertical offset similar to your example image.

* {
  box-sizing: border-box;
}

body {
  text-align: center;
  background: #131418;
}

.grid {
  max-width: 100%;
  margin: 0 auto;
  width: 95vw;
}

.grid-item {
  width: 50%;
  background: white;
  border: 2px #131418 solid;
}

.grid-item img {
  width: 100%;
  height: auto;
}

.grid-item p {
  font-size: 16px;
  padding: 2px 15px;
  text-align: justify
}

.grid-item:nth-of-type(2) {
  margin-top: 10em
}
<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>

<div class="grid" data-masonry='{ "itemSelector": ".grid-item"}'>
  <div class="grid-item"><img src="//via.placeholder.com/400x400" />
    <p>Lorem ipsum dolor sit amet, et equidem suscipit delicata eos. Simul scribentur delicatissimi te eam. Ius ea ullum dolorum disputando, pri putent definitiones et. Eos odio deleniti euripidis te, mea ex iudico praesent, et vix accusata percipitur. Ei
      nec quod lorem constituto. Eius intellegebat ad vis. Erat adipiscing conclusionemque mea at, omnesque cotidieque per ea. Oblique philosophia eos id, vel causae appellantur dissentiunt ad. Utroque corpora his an, suas ullamcorper nam ut. Nec iuvaret
      facilisi definiebas ea, ad omnium utamur ius.</p>
  </div>

  <div class="grid-item"><img src="//via.placeholder.com/500x500" />
    <p>Lorem ipsum dolor sit amet, sit prima oporteat ad, ad ridens tamquam his. Docendi platonem mea te, inani mentitum eum cu, in lorem eripuit debitis eum. Nam ei novum causae cotidieque, placerat similique at per, no his stet ferri animal. An option
      omittam invidunt vim. Dico aperiam cum te, his ei dicit civibus praesent, sed no salutandi hendrerit. Eam te inani verterem honestatis, id sit choro utroque pertinax. Sit cibo duis laoreet et, ea adhuc aliquam eum, mea paulo nostrum atomorum eu.
      Amet habeo semper ex vix, qui ea quas minimum. His at diam quaestio, ut hinc vocent principes eum. Ius sint movet labitur ea, per ad dignissim efficiendi. Idque assum vix at, diceret bonorum impedit eum ei, eos an duis decore deleniti. Duo dictas
      conceptam te.</p>
  </div>

  // More grid items go here

</div>


Just a heads-up: Angular offers a similar tool, although I lack personal experience with it.

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

Is there a way for me to achieve a vertical page turning effect on a single page?

I am seeking to develop a unique calendar display consisting of 12 images that give the illusion of flipping up when clicked. While I am aware of turn.js, my knowledge of javascript is limited and I need guidance on how to proceed. Despite having a program ...

The offset values of $(element) keep increasing indefinitely when they are updated repeatedly

After researching how to utilize JavaScript drag functionality to move elements, the goal is to dynamically adjust the cursor position within a square when dragged. In an attempt to simplify the process and avoid storing x and y offsets as separate variabl ...

Putting an <input/> element inside a Material UI's <TextField/> component in ReactJS - a beginner's guide

I am attempting to style <TextField/> (http://www.material-ui.com/#/components/text-field) to resemble an <input/>. Here is what I have tried: <TextField hintText='Enter username' > <input className="form-control ...

Set the default state of an input field to lowercase when using Angular

During our time working with AngularJs, we commonly utilized a default filter that would automatically convert input to lowercase. Unfortunately, this feature does not seem to be supported in Angular+. Can anyone confirm if this information is accurate? ...

Having trouble with your angular.jg ng controller functioning properly?

Having trouble getting any content to show up from the media object! The plate object seems to be malfunctioning. <!DOCTYPE html> <html lang="en" ng-app="confusionApp"> <head> <meta charset="utf-8"> <met ...

The angular js routing and translate template is malfunctioning and not functioning as expected

Just delving into the world of Angular and finding it quite fascinating! I'm currently designing a template for a promotional page but running into an issue - half of my script seems to have stopped working... If you'd like to take a look, here ...

Accessing deeply nested JSON objects in AngularJS

I've been working on an AngularJS single page application and I have successfully fetched files from a JSON. var app = angular.module("MyApp", []); app.controller("TodoCtrl", function($scope, $http) { $http.get('todos.json'). success ...

Customizing hyperlink styles with JavaScript on click

Hey there! I'm experimenting with something new. I've managed to change the background color of each link after it's clicked, but now I'm facing a challenge: How can I revert the original style when another link is clicked? Here's ...

Align the button to the right within the form

Having difficulty aligning a button to the right using float: right; No matter what I try, the button with the "advanced-search-button" class refuses to move to the right. This issue is occurring in Bootstrap 4. HTML <link href="https://maxcdn. ...

What is the best way to transmit a JSON object to REST services using Angular?

Whenever I attempt to send the JSON object to REST services, I encounter an error that looks like this: http://localhost:8080/api/v1/cardLimit 400 (Bad Request); JSON Object Example: public class GameLimit implements Serializable { private stati ...

Combining selected boxes through merging

Looking to create a simple webpage with the following requirements: There should be 10 rows and 3 boxes in each row. If I select 2 or more boxes or drag a box, they should merge together. For example, if my initial screen looks like this: and then I se ...

Sharing asynchronous data between AngularJS controllers

Among the multitude of discussions on sharing data between controllers, I have yet to come across a satisfactory solution for my particular scenario. In my setup, one controller fetches data asynchronously using promises. This controller then creates a co ...

The Bootstrap 5 class "col-md-4" seems to be malfunctioning

My goal is to create a grid layout with 3 columns and 2 rows using Bootstrap cards, but I'm encountering an issue where all the cards are centered and stacked on top of each other. Can someone please assist me in resolving this problem? Service.js co ...

How to retrieve the index of a nested ng-repeat within another ng-repeat loop

On my page, there is an array containing nested arrays that are being displayed using ng-repeat twice. <div ng-repeat="chapter in chapters"> <div ng-repeat="page in chapter.pages"> <p>Title: {{page.title}}</p> </d ...

Having trouble creating an angularjs table using ng-repeat in the controller?

I have a sample snippet that I would like to discuss. My goal is to display a JSON object in an angular table using ng-repeat, which is being generated from my angular controller script. I have attempted the code below, but for some reason, the table is no ...

Merge the "Checkbox" and "Avatar" components within an Ionic Framework List

As a proficient programmer new to the world of Ionic Framework and Angular.js, I am in the process of developing a mobile app using primarily "out of the box" features of Ionic. However, I have a specific requirement where I would like to create an Ionic l ...

Modify the paragraph content upon clicking

After experimenting with JavaScript to switch images, I now want to explore how to do the same with text. My dilemma lies in having 10 different paragraphs (where each link corresponds to a specific paragraph), but I'm unsure of where to input these ...

Adjusting the content of a span causes the parent element to shift to the left

I'm having trouble finding a solution to a specific issue that seems to be only affecting Chrome. Whenever I try to replace the text in a span element, it causes the parent anchor to shift left. You can see a demonstration of this problem here: http:/ ...

When using threejs, the color set for setClearColor is supposed to be white. However, when calling an external HTML file, it unexpectedly renders as

When I call an external HTML file in Three.js, the value for setClearColor is white but it renders as black. How can I solve this issue? Click here to view the image Here are the codes from the external file: <div id="3d-modal"></div> <sc ...

Angular UI modal using the powerful features of Bootstrap 4

Everything is working smoothly with Bootstrap 3 modal: https://jsfiddle.net/qLy7gk3f/4/ However, the same cannot be said for Bootstrap 4 modal: https://jsfiddle.net/qLy7gk3f/3/ The code remains unchanged: $scope.click = function() { $uibModal.open({ ...