skip to Main Content

Inspired by the design of a loop loom I am trying to make a pattern with html & css which will weave rows and columns inbetween eachother. My first attempt to accomplish this is to use css grid to place rows and columns, then relative positioning alongside z-index to choose which rows are above and below which columns. It works well for a single column, however once a second is added, there is no valid z-index for the column to not conflict with the first.

Here is a small example / mwe of my attempt.

html {
  display: grid;
  place-items: center;
}

body {
  display: grid;
  grid-template: 
    repeat(7, 1fr) /
    repeat(7, 1fr);
  gap: 5px;
}

.row, .col {
  padding: 2px;
  border-radius: 9in;
  position: relative;
  border: 10px solid;
}

.row {
  border-color: lightblue;
  grid-column: 1 / 8;
  grid-row-end: span 1;
}

.row:nth-of-type(odd) {
  z-index: 1;
}

.row:nth-of-type(even) {
  z-index: 3;
}

.row:nth-of-type(1) {
  grid-row-start: 2;
}

.row:nth-of-type(2) {
  grid-row-start: 3;
}

.row:nth-of-type(3) {
  grid-row-start: 4;
}

.row:nth-of-type(4) {
  grid-row-start: 5;
}

.row:nth-of-type(5) {
  grid-row-start: 6;
}

.col {
  border-color: tan;
  grid-row: 1 / 8;
  grid-column-end: span 1;
}

.col:nth-of-type(odd) {
  z-index: 2;
}

.col:nth-of-type(even) {
  /* no valid z-index to create pattern */
  /* z-index: ?????; */
  border-color: red;
}

.col:nth-of-type(1) {
  grid-column-start: 2;
}

.col:nth-of-type(2) {
  grid-column-start: 3;
}

.col:nth-of-type(3) {
  grid-column-start: 4;
}

.col:nth-of-type(4) {
  grid-column-start: 5;
}

.col:nth-of-type(5) {
  grid-column-start: 6;
}

:is(.col, .row):hover {
  border-color: green;
}
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<span class="col"></span>
<span class="col"></span>
<span class="col"></span>
<span class="col"></span>
<span class="col"></span>

I intend to incorporate the design into a simple react app which will allow dynamic control of rows/cols and changing colors, using it for visualizing different patterns before committing.

How can I create the weave / loop loom pattern in html & css?

2

Answers


  1. You could make a mix of z-index and clip-path. z-index on its own cannot do this, nor transform 3D

    Here is an example:

    html {
      display: grid;
      place-items: center;
      min-height:100vh;
    }
    
    body {
      display: grid;
      grid-template: 
        repeat(7, 1fr) /
        repeat(7, 1fr);
      gap: 5px;
      width:50vmin;
      aspect-ratio:1;
    }
    
    .row, .col {
      padding: 2px;
      border-radius: 9in;
      position: relative;
    }
    
    .row {
      background: lightblue;
      grid-column: 1 / 8;
      grid-row-end: span 1;
    }
    
    
    .row:nth-of-type(1) {
      grid-row-start: 2;
    }
    
    .row:nth-of-type(2) {
      grid-row-start: 3;
    }
    
    .row:nth-of-type(3) {
      grid-row-start: 4;
    }
    
    .row:nth-of-type(4) {
      grid-row-start: 5;
    }
    
    .row:nth-of-type(5) {
      grid-row-start: 6;
    }
    
    .col {
      background: tan;
      grid-row: 1 / 8;
      grid-column-end: span 1;
    }
    
    .col:nth-of-type(even) {
      background: red;
    }
    
    .col:nth-of-type(1) {
      grid-column-start: 2;
    }
    
    .col:nth-of-type(2) {
      grid-column-start: 3;
    }
    
    .col:nth-of-type(3) {
      grid-column-start: 4;
    }
    
    .col:nth-of-type(4) {
      grid-column-start: 5;
    }
    
    .col:nth-of-type(5) {
      grid-column-start: 6;
    }
    
    :is(.col, .row):hover {
      border-color: green;
    }
    
    body > :nth-child(odd) {
      z-index:2
    }
    
    body>:nth-child(7),
    body>:nth-child(9) {
      clip-path: polygon(0% 0%, 0% 29%, 100% 29%, 100% 42%, 0% 42%, 0% 58%, 100% 58%, 100% 71%, 0% 71%, 0% 100%, 100% 100%, 100% 0%);
    }
    <div class="row"></div>
    <div class="row"></div>
    <div class="row"></div>
    <div class="row"></div>
    <div class="row"></div>
    <span class="col"></span>
    <span class="col"></span>
    <span class="col"></span>
    <span class="col"></span>
    <span class="col"></span>

    here is a generator for clip-path of a great help to start a pattern https://bennettfeely.com/clippy/ (note that the path can be applied to shape-outside , but that is for another purpose )

    Login or Signup to reply.
  2. One way to do this is to have the pattern as background images.

    This snippet sets the warp up as vertical stripes as background to the container’s before pseudo element using to right linear-gradients.

    This gives this sort of pattern:

    enter image description here

    Then we add the wefts one line each as background to the after pseudo element. This time they are 50% the required color and 50% transparent, which allows the warp to show.

    I’ve added a bit of JavaScript to create the CSS – just alter the width of the container to be whatever you want and set up the warp and weft colors as arrays.

    const weave = document.querySelector('.weave');
    const warpColors = ['cyan', 'magenta', 'yellow'];
    const weftColors = ['red', 'green', 'blue', 'orange'];
    
    const wpn = warpColors.length;
    const wfn = weftColors.length;
    
    weave.style.setProperty('--wpn', wpn);
    weave.style.setProperty('--wfn', wfn);
    
    let warpBackgroundImage = '';
    let weftBackgroundImage = '';
    let weftBackgroundPositionY = '';
    
    // go through building up the warps
    for (let i = 0; i < wpn; i++) {
      warpBackgroundImage += ', ' + warpColors[i] + ' calc(' + i + ' * var(--s)) calc(' + (i + 1) + ' * var(--s))';
    }
    weave.style.setProperty('--wpbg', 'linear-gradient(to right' + warpBackgroundImage + ')');
    
    // go through building up the wefts
    for (let i = 0; i < wfn; i++) {
      weftBackgroundImage += ((i == 0) ? '' : ', ') + 'linear-gradient(to right, ' + ((i % 2 == 0) ? ('transparent 50%, ' + weftColors[i] + ' 50%)') : (weftColors[i] + ' 50%, transparent 50%)'));
    
      weftBackgroundPositionY += ((i == 0) ? '' : ',') + 'calc(' + i + '* var(--s))';
    }
    weave.style.setProperty('--wfbg', weftBackgroundImage);
    weave.style.setProperty('--wfbgposy', weftBackgroundPositionY);
    * {
      margin: 0;
    }
    
    .weave {
      --w: 75vmin;
      width: var(--w);
      aspect-ratio: calc(var(--wpn) / var(--wfn));
      position: relative;
      /* size of square */
      --s: calc(var(--w) / var(--wpn));
    }
    
    .weave::before,
    .weave::after {
      content: '';
      position: absolute;
      width: 100%;
      height: 100%;
      z-index: -1;
    }
    
    
    /* the warp */
    
    .weave::before {
      background-image: var(--wpbg);
    }
    
    
    /* the weft */
    
    .weave::after {
      background-image: var(--wfbg);
      background-repeat: repeat no-repeat;
      background-size: calc(2 * var(--s)) var(--s);
      background-position-y: var(--wfbgposy);
    }
    <div class="weave"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search