3

There is a pattern I'd like to rebuild in HTML and CSS only:

offset every odd row of dots

As I imagined it I'd need to have a collection of elements (here displayed as dots) which are lined up next to each other and which have a specific margin. I can then try to add a larger margin to every nth instance of a dot, which starts a new row, to offset the row which it is located in. I created an example here:

wrapper {
  width: 100%;
}
.dot {
  width: 150px;
  height: 150px;
  margin: 15px;
  border-radius: 50%;
  display: inline-block;
  background-color: #999;
}
.wrapper .dot:nth-child(4n) {
  margin-left: 100px;
  background-color: #dd77dd;
}
<div class="wrapper">
  <div class="dot">Element 1</div>
  <div class="dot">Element 2</div>
  <div class="dot">Element 3</div>
  <div class="dot">Element 4</div>
  <div class="dot">Element 5</div>
  <div class="dot">Element 6</div>
</div>

You can also edit it in this fiddle: https://jsfiddle.net/jessicajordan/j8238oo6/8/

This setup works completely fine for a fixed width layout, e.g. when the .wrapper container, in which the dot elements are contained is of a predefined and fixed width. However, I want to make the container width responsive (e.g. set it to 100% width and make its width adjustable by viewport size), which means that the rows of dots can contain a varying number of dot elements depending on the flexible size of the .wrapper container. Therefore the dot element that starts a new row and which is supposed to add an offset to it by using a bigger margin than the other dots, will be a different one each time the .wrapper container size changes.

If it is doable in HTML + CSS alone: How can I add an offset to every 2nd row of elements and preserve this layout across different container sizes? Just mentioning: the dot elements themselves should have a fixed width and should not scale in size with the .wrapper container.

web-tiki
  • 99,765
  • 32
  • 217
  • 249
jessica
  • 480
  • 6
  • 17
  • is there a fix or max number of dots? – web-tiki Jan 08 '16 at 14:43
  • Good question - in my setup it will never be more than 30 dots. Although there are no guidelines about a fixed number of dots yet. Any solution for 12-30 dots is fine. – jessica Jan 08 '16 at 14:48
  • Are dots going to remain a fixed size? Could possibly use Media queries at each break of a new row if dot is a known size. – Andrew Clody Jan 08 '16 at 15:02
  • @AndrewClody Yes they are going to remain the same size. In fact, you're right it's not that difficult to implement it this way with maybe 3 dots per line - three different media queries should be fine then to add the margin to specific dot elements. But is there a more elegant way for maybe a dozen dots per line? – jessica Jan 08 '16 at 15:06
  • If that matters for something, creating this pattern with a repeating background and `css-gradients` is a piece of cake. Still thinking if there is a good way to make this work dynamically with elements and styling them, but seems like it is a real challenge. – Clemens Himmer Jan 08 '16 at 15:16

3 Answers3

2

One way you can offset every odd row with CSS only and without media queries is to use the shape-outside property.
Please note that this property is candidate recomendation and therefore has low browser support.

Here is an example that supports up to 5 rows :

.wrapper {
  width: 100%;
}
.wrapper div {
  width: 50px;
  height: 50px;
  margin: 50px;
  border-radius: 50%;
  display: inline-block;
  background-color: #000;
  text-align: center;
}
.wrapper:before {
  content: '';
  float: left;
  width: 75px;
  height: 9999px;
  -webkit-shape-outside: polygon(0px 150px, 75px 150px, 75px 300px, 0 300px, 0px 450px, 75px 450px, 75px 600px, 0px 600px);
  shape-outside: polygon(0px 150px, 75px 150px, 75px 300px, 0 300px, 0px 450px, 75px 450px, 75px 600px, 0px 600px);
}
<div class="wrapper">
  <div></div><div></div><div></div><div></div><div></div>
  <div></div><div></div><div></div><div></div><div></div>
  <div></div><div></div><div></div><div></div><div></div>
  <div></div><div></div><div></div><div></div><div></div>
</div>
web-tiki
  • 99,765
  • 32
  • 217
  • 249
  • How does that `poligon` function work in combination with the `shape-outside`? Looks like something hard-coded, also tried adding some more elements with your code, did not work, seems to me like it is non-flexible. – Clemens Himmer Jan 08 '16 at 15:22
  • @Tarekis the polygon is hand coded and needs to be made for the max number of possible rows. In my example, there are only 5 possible rows. – web-tiki Jan 08 '16 at 15:24
  • thought that would be the case, i can't really decode what the `polygon` does anymore to be honest. Seems like a not-prefect answer to me, not sure if its is even possible to do this CSS only at all, can't really think of a perfect answer either. PS: Saw your codepen, nice stuff! `;)` – Clemens Himmer Jan 08 '16 at 15:28
  • @Tarekis thx. And you are right, this isn't a perfect solution especialy considering browser support. – web-tiki Jan 08 '16 at 15:47
  • Holy Moly, this one is a cracker! Made a solution that works with any number of items, but it seems to be impossible to not have at least one limitation. – Clemens Himmer Jan 08 '16 at 16:20
  • 1
    Browser support is still pretty subtle with only current releases of Chrome, Safari and Opera enabling the shape-outside property, but this is still the most fitting solution to the described problem. – jessica Jan 11 '16 at 10:00
0

Here is another approach you could look at :

HTML

<div class="wrapper">
  <div class="float-right"></div>
  <div class="float-left"></div>
  <div class="float-right"></div>
  <div class="dot">Element 1</div>
  <div class="dot">Element 2</div>
  <div class="dot">Element 3</div>
  <div class="dot">Element 4</div>
  <div class="dot">Element 5</div>
  <div class="dot">Element 6</div>
  <div class="dot">Element 7</div>
  <div class="dot">Element 8</div>
  <div class="dot">Element 9</div>
  <div class="dot">Element 10</div>
  <div class="dot">Element 11</div>
  <div class="dot">Element 12</div>
</div>

CSS

wrapper {
  width: 100%;
}
.dot {
  width: 150px;
  height: 150px;
  margin: 15px;
  border-radius: 50%;
  display: inline-block;
  background-color: #999;
}

.float-left, .float-right {
  border: doted blue 1px; /* temporary */
  width: 100px;
  height: 180px;
}
.float-left {
  float: left;
  clear: right;
}
.float-right {
  float: right;
  clear: left;
}

Instead of trying to put margin on some elements, you create floating "obstacles" in the page to move the dots on the left or right.

You can display as many floating divs as you need, but the thing is you must hide them when using smaller screen resolution, when they become "dot-less" on the bottom of the page. I think you can manage that with media queries or bootstrap classes, conditionning the number of floating divs with the screen resolution.

Eria
  • 2,653
  • 6
  • 29
  • 56
0

Okay that took me some thinking, but i think i got something rather acceptable, it will work in every enviorment, page size and any number of dots.

It altough has one limitation! You have to fix the number of dots per row.

Let's see, i choose to use 9 dots on a full row, making it really easy to calculate, as you have to split your width into whatever amount of dots you choose + 1, as there is always a half dot's width space on either the left or right side.

HTML:

You'll repeat blocks of this codes:

  <div class="container">
      <div class="dummy"></div>
      <div class="element">
      </div>
  </div>

With a really smart trick by Nathan Ryan you can now choose your elements to be any width and their height will adapt.

CSS:

Now comes a bit of calculating (you could use less or sass to calculate this dynamically and change the number of dots per row). I'll comment in the code to make understanding what these properties do.

.container {
    display: inline-block;
    position: relative;
    /* As i want to calculate for 10 dots i have to make a dot + margin take up
    exactly 10% of the document's width, here i chose a 3/4 ratio per dot*/
    width: 7.5%;    
    margin-right: 2.5%;
}


/* Here you have to choose every (rowLength)*2 and add 1 or (rowLength) + 1, 
depending which line you want your offset to start */
.wrapper .container:nth-child(18n+10) {  
    /* And finally align it half of a dot's complete size*/
    margin-left: 5%;
}
.dummy {
    margin-top: 100%;
}
.element {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    border-radius: 50%;
    display: inline-block;
    background-color: #f1ea75;
}

You can check it out here.

..and yeah i know, the bears are awesome! (ง⚆ᴥ⚆)ง

Community
  • 1
  • 1
Clemens Himmer
  • 1,340
  • 2
  • 13
  • 26
  • Sorry but I don't see how this answers the question. The OP explicitly specifies that the dots width/height should be fixed and is already using the `nth-child()` selector to offset even rows in the example. This said, the approach you are using is great and allows [awesome layouts](http://codepen.io/web-tiki/pen/qObavb) (combined with media queries) – web-tiki Jan 08 '16 at 16:39
  • If that is true i must have mis-read/understood the question, what a pity. I interpreted she wants responsive width dots, well not going for another aproach now. :/ Still, hooray for the bears? – Clemens Himmer Jan 08 '16 at 16:42
  • @web-tiki just what i wanted to hear! haha :D – Clemens Himmer Jan 08 '16 at 16:43
  • @Tarekis - Yes, I'd like to have fixed width dots, although I find your approach also very creative and am sure it will help others searching for this or a similar question – jessica Jan 11 '16 at 09:54
  • @jessica thank you, i appreciate your kind comment. i soon understood that my answer is not an applicable solution, what a pity, let's hope it helps anyone anywhen then! `(ง⚆ᴥ⚆)ง` – Clemens Himmer Jan 11 '16 at 10:06