How do I add visual border, from image, that is flexible and scalable?

34 Views Asked by At

The image here is just an example of what it is I'm trying to do. I have containers (left, main, right) and I want a visualized border, which I assume I will do via image of some sort. I honestly have no idea what they used here, nor how to create my own version of it with new artwork. Image of example border

I created a border image and now my website looks like a potato chunk slicer But then after messing with the settings, it now looks like this:

enter image description here

At first I had utilized a picture of a border and just added 'border, like this here: small version of a 2048x2048 image

That looked like this when implemented on the site: enter image description here

That made it look like this, which I guess isn't too terrible and more in line with my goal. I added this line to my index.html to get the above image:

border-image: url("{{ url_for('static', filename='border.png')}}") 16 round;

That wasn't what I wanted so I went into photoshop and created a border_top, _bottom, _left, _right and then tried to slice it and boy did it go wonky.

Image of border image: enter image description here

I only list one, but the others are just like it and are separated by side.

Then I tried this:

.container {
    position: relative;
    display: grid;
    grid-template-columns: 1fr 3fr 1fr;  /*Adjust the fr units as per your design */
    gap: 10px;
    height: 100vh; /* Use the full height of the viewport */
}

.container::before,
.container::after {
    content: '';
    position: absolute;
    pointer-events: none;
}

.container::before { /* Top and bottom border */
    top: 0; right: 0; bottom: 0; left: 0;
    height: 100%;
    border: solid transparent;
    border-width: 16px 0; /* Top and bottom borders */
    background-repeat: round;
    background-image: url('border_top.png'), url('border_bottom.png');
    background-position: top, bottom;
    background-size: 100% 16px; /* Scale to the container width */
}

.container::after { /* Left and right border */
    top: 0; right: 0; bottom: 0; left: 0;
    width: 100%;
    border: solid transparent;
    border-width: 0 16px; /* Left and right borders */
    background-repeat: round;
    background-image: url('border_left.png'), url('border_right.png');
    background-position: left, right;
    background-size: 16px 100%; /* Scale to the container height */

and I ended up with the above picture of the potato chunk slicer. lol

Fair warning - I do NOT know what is standard for creating borders. Is there a way to take just a high-resolution texture and turn it into a border or do I have to create a border in the exact dimensions of each .container? Or? I have scoured the interwebs and see that using images as borders is problematic, but it was done in the above image so I'd like to try to get something similar in mine.

All help is appreciated. For the record, I have played around with all px sizes within. Some of them change the waffle pattern slightly but nothing that appears to fix the problem.

This is my index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My RPG Game</title>
    <link
      rel="stylesheet"
      href="{{ url_for('static', filename='style.css') }}"
    />
    <style>
      .main-content {
        position: relative;
        border: 16px solid transparent;
        /*border-image: url("{{ url_for('static', filename='border.png')}}") 16
          round;*/
      }
      .main-content::before {
        content: "";
        position: absolute;
        top: -16px;
        left: 0;
        width: 100%;
        height: 16px;
        background: url("{{ url_for('static', filename='border_top.png') }}")
          repeat-x;
      }
      /* Bottom border */
      .main-content::after {
        content: "";
        position: absolute;
        bottom: -16px;
        left: 0;
        width: 100%;
        height: 16px;
        background: url("{{ url_for('static', filename='border_bottom.png') }}")
          repeat-x;
      }
      .sidebar-left {
        border: 16px solid transparent;
        border-image: url("{{ url_for('static', filename='border.png')}}") 16
          round;
      }
      .sidebar-right {
        border: 16px solid transparent;
        border-image: url("{{ url_for('static', filename='border.png')}}") 16
          round;
      }
      /* Left border */
      .sidebar-left::before {
        content: "";
        position: absolute;
        top: 0;
        left: -16px;
        width: 16px;
        height: 100%;
        background: url("{{ url_for('static', filename='border_left.png') }}")
          repeat-y;
      }

      /* Right border */
      .sidebar-right::after {
        content: "";
        position: absolute;
        top: 0;
        right: -16px;
        width: 16px;
        height: 100%;
        background: url("{{ url_for('static', filename='border_right.png') }}")
          repeat-y;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <aside class="sidebar-left">
        <!-- Character's location and stats go here -->
      </aside>
      <main class="main-content">
        <!-- Main game content and chat area go here -->
        <div class="chat">
          <!-- Chat content goes here -->
        </div>
        <div class="inventory">
          <!-- Inventory list goes here -->
        </div>
        <!-- Add additional sections as needed -->
      </main>
      <aside class="sidebar-right">
        <!-- Additional information or ads could go here -->
      </aside>
    </div>
    <script src="{{ url_for('static', filename='script.js') }}"></script>
  </body>
</html>

This is my full style.css:

/* Reset margins and padding */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* Container for the entire layout */
.container {
    position: relative;
    display: grid;
    grid-template-columns: 1fr 3fr 1fr;  /*Adjust the fr units as per your design */
    gap: 10px;
    height: 100vh; /* Use the full height of the viewport */
}

.container::before,
.container::after {
    content: '';
    position: absolute;
    pointer-events: none;
}

.container::before { /* Top and bottom border */
    top: 0; right: 0; bottom: 0; left: 0;
    height: 100%;
    border: solid transparent;
    border-width: 16px 0; /* Top and bottom borders */
    background-repeat: round;
    background-image: url('border_top.png'), url('border_bottom.png');
    background-position: top, bottom;
    background-size: 100% 16px; /* Scale to the container width */
}

.container::after { /* Left and right border */
    top: 0; right: 0; bottom: 0; left: 0;
    width: 100%;
    border: solid transparent;
    border-width: 0 16px; /* Left and right borders */
    background-repeat: round;
    background-image: url('border_left.png'), url('border_right.png');
    background-position: left, right;
    background-size: 16px 100%; /* Scale to the container height */
}


.sidebar-left,
.sidebar-right {
    background-color: #806c50; /* Example color */
    /* Add more styling */
}

.main-content {
    border-top: 16px solid transparent;
    border-right: 16px solid transparent;
    border-bottom: 16px solid transparent;
    border-left: 16px solid transparent;
    border-image-source: url('/static/border_top.png') 16 round, 
                         url('/static/border_right.png') 16 round, 
                         url('/static/border_bottom.png') 16 round, 
                         url('/static/border_left.png') 16 round;
    border-image-slice: 200;
    border-image-repeat: repeat;
    display: grid;
    grid-template-rows: 1fr auto; /* Adjust the row sizes as needed 
    gap: 10px;*/
}

.chat {
    background-color: #5c4838; /* Example color */
    overflow-y: auto; /* If you want the chat to be scrollable */
    /* Add more styling */
}

.inventory {
    overflow-y: auto; /* Scrollable list of items */
    /* Add more styling */
}

/* Responsive design */
@media (max-width: 768px) {
    .container {
        grid-template-columns: 1fr; /* Stack sidebars and content on smaller screens */
    }

    .sidebar-left,
    .sidebar-right {
        display: none; /* Hide sidebars on smaller screens, or adjust as needed */
    }

    .main-content {
        border-image: none; /* Remove the border image on smaller screens if needed */
        grid-template-rows: auto; /* Adjust layout for mobile */
    }
}

Edit #1:

Okay, so I have fixed the potato slicer view, but I'm basically where I was at from the start.

I commented out this line:

/*.container::before,
.container::after {
content: '';
position: absolute;
pointer-events: none;
}*/

That made it look like this:

enter image description here

1

There are 1 best solutions below

0
Newbie On

Okay, so I have fixed it!

Here is my updated, and completely rewritten code:

    /* Reset margins and padding */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* Main wrapper for the layout */
.wrapper {
    display: flex; 
    justify-content: space-between; 
    height: 100vh; 
    padding: 16px; 
    background: #806c50; 
}

/* Common styles for sidebars and main content */
.container {
    background-color: #806c50; 
    overflow-y: auto; 
}

/* Styles for the left sidebar */
.sidebar-left {
    flex: 1; 
    margin-right: 10px; 
}

/* Styles for the main content area */
.main-content {
    flex: 3; 
    margin-right: 10px; 
}

/* Styles for the right sidebar */
.sidebar-right {
    flex: 1; 
}

/* Apply the borders */
.container {
    border-style: solid;
    border-width: 16px; 
    border-image-source: url('/static/border.png');
    border-image-slice: 30 fill;
    border-image-width: 16px;
    border-image-outset: 0; 
    border-image-repeat: stretch; 
}

/* Responsive design adjustments for smaller screens */
@media (max-width: 768px) {
    .wrapper {
        flex-direction: column; /* Stack containers vertically on small screens */
    }

    .sidebar-left,
    .sidebar-right {
        order: 1; /* Put sidebars after main content on small screens */
        margin-right: 0; 
        margin-bottom: 10px; 
    }

    .main-content {
        order: 0; 
        margin-right: 0; 
    }
}

Here's my index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My RPG Game</title>
    <link
      rel="stylesheet"
      href="{{ url_for('static', filename='style.css') }}"
    />
  </head>
  <body>
    <div class="wrapper">
      <div class="container sidebar-left">
        <!-- Character's location and stats go here -->
      </div>
      <div class="container main-content">
        <div class="chat">
          <!-- Chat content goes here -->
        </div>
        <div class="inventory">
          <!-- Inventory list goes here -->
        </div>
        <!-- Add additional sections as needed -->
      </div>
      <div class="container sidebar-right">
        <!-- Additional information or ads could go here -->
      </div>
    </div>
    <script src="{{ url_for('static', filename='script.js') }}"></script>
  </body>
</html>

While it's not perfect yet, I think I now understand how to do what I need to do.