Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Feature Request Please implement grid layout and the gap property

Discussion in 'UI Toolkit' started by pbhogan, Feb 27, 2023.

  1. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    375
    This may already be on the internal roadmap, but please implement a display grid layout (https://www.w3schools.com/css/css_grid.asp) and the gap property (https://www.w3schools.com/cssref/css3_pr_gap.php) for both flex and grid layouts.

    These are commonly used in web development and they align well with common visual design patterns used in game development.

    Gap is especially useful. There really isn't another way to accomplish proper spaces between child items that also works with wrapping. Even in CSS, the hacks necessary using :first-child and :last-child pseudo-classes or negative margins are just a pain that gap solves perfectly.
     
    Last edited: Feb 27, 2023
  2. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    515
    Hi!

    Yes, theses are really practical. We need to finish some refactor to improve the layout and style performance before adding the gap property and the grid layout.

    You can go on the roadmap and upvote the issue here:
    https://unity.com/roadmap/unity-platform/ui
     
  3. ElevenArt

    ElevenArt

    Joined:
    Dec 12, 2012
    Posts:
    16
    I agree, with grid and gap properties the UI Toolkit would be much easier to use.

    I made a small example, retro style security door's panel, just a visual in pure html and css without images in web browser and now the magic begins :)

    1.png 2 Number click.png 3 Sucess.png

    Here's my code for example of usage:

    <!DOCTYPE html>
    <html lang="sk">
    <head>
    <title>Retro style security door's panel</title>
    <style type="text/css">
    * {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    }

    :root {
    --logo-text-gradient: linear-gradient(to right, #444, #555, #666, #444, #666, #444, #444);
    }

    .metal-wall {
    display: flex;
    height: 100vh;
    justify-content: center;
    align-items: center;
    background: linear-gradient(to right, #555, #aaa, #777, #999);
    }

    .security-door-panel {
    display: flex;
    flex-direction: column;
    width: 1000px;
    height: 620px;
    padding: 40px 100px 80px 100px;
    background: linear-gradient(to right, #888, #ccc, #999, #bbb, #888);
    border-radius: 10px;
    box-shadow: 0 8px 20px 5px rgba(0,0,0,0.6);
    }

    .logo-container {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-basis: 100px;
    margin-bottom: 40px;
    }
    .logo-text {
    font-family: Impact;
    font-size: 60px;
    color: rgba(255,255,255,0);
    background: var(--logo-text-gradient);
    background-clip: text;
    }

    .password-section-container {
    flex-grow: 1;
    display: grid;
    grid-template-columns: 500px 1fr 1fr 1fr;
    gap: 15px;
    }

    .monitor {
    grid-row: 1 / span 4;
    display: flex;
    justify-content: center;
    align-items: center;
    margin-right: 45px;
    background-color: #222;
    border: 1px solid #444;
    border-radius: 20px;
    box-shadow: 0 3px 10px 0 rgba(0,0,0,0.7), inset 0 -5px 25px 1px rgba(180,180,180,0.8);
    }

    .monitor-text {
    display: flex;
    font-family: monospace;
    font-size: 35px;
    font-weight: bold;
    color: greenyellow;
    }

    button {
    display: flex;
    justify-content: center;
    align-items: center;
    font-family: Helvetica;
    font-size: 20px;
    font-weight: bold;
    color: MediumSeaGreen;
    background-color: #ddd;
    border: none;
    border-radius: 2px;
    box-shadow: 0 3px 6px 0 rgba(0,0,0,0.7);
    transition: all 0.15s;
    }
    button:active {
    color: lime;
    background-color: MediumSeaGreen;
    transform: scale(0.98,0.98);
    box-shadow: 0 3px 4px 0 rgba(0,0,0,0.3);
    }

    .enter {
    color: green;
    background-color: MediumSeaGreen;
    }
    .enter:active {
    color: MediumSeaGreen;
    background-color: lightgreen;
    }

    .cancel {
    color: darkred;
    background-color: red;
    }
    .cancel:active {
    color: chocolate;
    background-color: lightsalmon;
    }

    </style>
    </head>
    <body>
    <section class="metal-wall">
    <div class="security-door-panel">
    <div class="logo-container">
    <div class="logo-text">SecurityTech Corp.</div>
    </div>
    <div class="password-section-container">
    <div class="monitor">
    <span class="monitor-text">_ _ _ _ _ _</span>
    </div>
    <button>1</button>
    <button>2</button>
    <button>3</button>
    <button>4</button>
    <button>5</button>
    <button>6</button>
    <button>7</button>
    <button>8</button>
    <button>9</button>
    <button class="cancel">Cancel</button>
    <button>0</button>
    <button class="enter">Enter</button>
    </div>
    </div>
    </section>
    </body>
    </html>


    I used:
    • combination of flex and grid with gap property
    • grid, gap and grid-row properties for monitor and buttons (in .password-section-container class, grid-row property in .monitor class)
    • box-shadow and linear gradients
    • background-clip for clipping linear-gradient background to logo text, just for fun :)

    Of course, through the UI Toolkit, the usage of this, maybe in the future, would be possible with little differents, but similarly.

    Have a nice day, good luck :cool:
     
    Last edited: May 24, 2023
    GDevTeam likes this.
  4. ElevenArt

    ElevenArt

    Joined:
    Dec 12, 2012
    Posts:
    16
    There is the other version of a retro style security door's panel. This layout is completely made with 2 grids and flex is used only for alignment. Result is the same.

    Html code:

    <body>
    <section class="metal-wall">
    <div class="security-door-panel">
    <div class="logo-container">
    <div class="logo-text">SecurityTech Corp.</div>
    </div>
    <div class="monitor-container">
    <div class="monitor">
    <span class="monitor-text">_ _ _ _ _ _</span>
    </div>
    </div>
    <div class="buttons-container">
    <button>1</button>
    <button>2</button>
    <button>3</button>
    <button>4</button>
    <button>5</button>
    <button>6</button>
    <button>7</button>
    <button>8</button>
    <button>9</button>
    <button class="cancel">Cancel</button>
    <button>0</button>
    <button class="enter">Enter</button>
    </div>
    </div>
    </section>
    </body>


    And here is css:

    <style type="text/css">
    * {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    }

    :root {
    --logo-text-gradient: linear-gradient(to right, #444, #555, #666, #444, #666, #444, #444);
    }

    .metal-wall {
    display: flex;
    height: 100vh;
    justify-content: center;
    align-items: center;
    background: linear-gradient(to right, #555, #aaa, #777, #999);
    }

    .security-door-panel {
    display: grid;
    grid-template-columns: 455px 1fr;
    grid-template-rows: 100px 1fr;
    gap: 40px 60px;

    width: 1000px;
    height: 620px;
    padding: 40px 100px 80px 100px;
    background: linear-gradient(to right, #888, #ccc, #999, #bbb, #888);
    border-radius: 10px;
    box-shadow: 0 8px 20px 5px rgba(0,0,0,0.6);
    }

    .logo-container {
    grid-column: 1 / span 2;
    display: flex;
    justify-content: center;
    align-items: center;
    }
    .monitor-container {
    display: flex;
    height: 100%;
    }
    .buttons-container {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 15px;
    }

    .logo-text {
    font-family: Impact;
    font-size: 60px;
    color: rgba(255,255,255,0);
    background: var(--logo-text-gradient);
    background-clip: text;
    }

    .monitor {
    display: flex;
    flex-grow: 1;
    justify-content: center;
    align-items: center;
    background-color: #222;
    border: 1px solid #444;
    border-radius: 20px;
    box-shadow: 0 3px 10px 0 rgba(0,0,0,0.7), inset 0 -5px 25px 1px rgba(180,180,180,0.8);
    }
    .monitor-text {
    display: flex;
    font-family: monospace;
    font-size: 35px;
    font-weight: bold;
    color: greenyellow;
    }

    button {
    display: flex;
    justify-content: center;
    align-items: center;
    font-family: Helvetica;
    font-size: 20px;
    font-weight: bold;
    color: MediumSeaGreen;
    background-color: #ddd;
    border: none;
    border-radius: 2px;
    box-shadow: 0 3px 6px 0 rgba(0,0,0,0.7);
    transition: all 0.15s;
    }
    button:active {
    color: lime;
    background-color: MediumSeaGreen;
    transform: scale(0.98,0.98);
    box-shadow: 0 3px 4px 0 rgba(0,0,0,0.3);
    }

    .enter {
    color: green;
    background-color: MediumSeaGreen;
    }
    .enter:active {
    color: MediumSeaGreen;
    background-color: lightgreen;
    }

    .cancel {
    color: darkred;
    background-color: red;
    }
    .cancel:active {
    color: chocolate;
    background-color: lightsalmon;
    }
    </style>


    In this css code, no margins are used, only gaps. First grid is used for layout (containers, in .logo-container class I used grid-column property) and second grid is used for buttons. This is easily, fastest and much clearer way to use grids.
     
    Last edited: May 24, 2023