skip to Main Content

I’m having troubles with some css distribution using flexbox or grid layout, here’s the thing:

I have a container with the next disposition (75% input, 25% button):
first_request

That disposition should be the main disposition in desktop and large screens.

However, the request is that, once the container reaches the mobile width, the container should change the proportion of the elements (50% input, 50% button):
second_request

This would be easily achievable with media queries, but the request is to use only grid css or flexbox (or both, anything but media queries)

Here’s a simple HTML and CSS of some attempts

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <link rel="stylesheet" href="index.css">
            <title>Document</title>
        </head>
    <body>
        <div class="container">
            <input type="text" class="input" />
            <button class="button">Button</button>
          </div>
    </body>
    </html>

CSS 1 (First try, flexbox):

    * {
      box-sizing: border-box; /* Include padding and borders in width calculations */
    }

    .container {
      display: flex;
      width: 100%; /* Full width of the parent */
    }

    .input {
      flex-grow: 1;      /* Input can grow to fill space */
      flex-shrink: 1;    /* Input can shrink */
      flex-basis: 75%;   /* Start at 75% width */
      min-width: 50%;    /* Minimum width is 50% */
    }

    .button {
      flex-grow: 0;      /* Button does not grow */
      flex-shrink: 1;    /* Button can shrink */
      flex-basis: 25%;   /* Start at 25% width */
      min-width: 25%;    /* Minimum width is 25% */
      max-width: 50%;    /* Maximum width is 50% */
    }

CSS 2 (Second try, using CSS grid):

    * {
      box-sizing: border-box; /* Include padding and borders in width calculations */
    }

    .container {
      display: grid;
      grid-template-columns: 75% 25%; /* Initial layout for desktop */
      width: 100%; /* Full width of the parent */
    }

    .input {
      min-width: 50%; /* Input can shrink to a minimum of 50% */
    }

    .button {
      min-width: 25%; /* Button maintains a minimum width of 25% */
    }

The thing is, that the proportions stay in 75% to 25% (75% input, 25% button) in desktop AND mobile (not changing when shrinking the screen, or in 50% – 50% in desktop AND mobile (not stretching when changing to Desktop, but can’t achieve both behaviors on different screen sizes with only one code implementation

My question is, is this problem achievable with plain css grid or/and flexbox? or is this only achievable with media queries?

Thanks in advance!

2

Answers


  1. You can do this without media queries by using CSS calc, clamp and cqw units.

    This snippet sets a variable, –w, to 0cqw if the width is below 600px [defined as ‘mobile’ for this example, alter to what you consider mobile width to be] and 1cqw if it is above.

    The widths of input and container are calculated using this.

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link rel="stylesheet" href="index.css">
      <title>Document</title>
      <style>
        .container {
          width: 100%;
          --w: clamp(0cqw, calc(100vw - 600px), 1cqw);
          display: flex;
          gap: 0;
        }
        /* --w is 0cqw if the viewport is less than 600px wide otherwise it is 1cqw*/
        
        .input {
          width: calc((var(--w) * 75) + ((1vw - var(--w)) * 50));
        }
        
        .button {
          width: calc((var(--w) * 25) + ((1vw - var(--w)) * 50));
        }
      </style>
    </head>
    
    <body>
      <div class="container">
        <input type="text" class="input" />
        <button class="button">Button</button>
      </div>
    </body>
    
    </html>
    Login or Signup to reply.
  2. You can do it like below

    .container {
      display: flex;
    }
    .container > * {
      flex: 1;
    }
    
    .container > input {
      /* 
         if (container width < 600px) 
           min-width = 0
         else 
           min-width = 75%
      */
      min-width: min(75%, calc((100% - 600px)*999));
    }
    <div class="container">
      <input type="text" class="input" />
      <button class="button">Button</button>
    </div>

    Read my article for more tricks like the above: https://css-tricks.com/responsive-layouts-fewer-media-queries/

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search