Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a repeated border for a responsive element?

Tags:

html

css

border

svg

What I want to create:

  • a dotted border on top of each li-element
  • the size of the dots and margin between them can change by tweaking the CSS or the image/SVG used)
  • the width of the ul is responsive, so the border's width varies, too
  • dots should not be cut/truncated when resizing the viewport, that means only full cirlces should be visible

tl;dr: I don't want this to happen (see the last dot?) when resizing the viewport:

enter image description here

I can't think of a way to create this using:

  • repeated background image
  • a huge (very long) background image
  • border-image

What I got:

I figured out a way to solve it, but it's really annoying. It works, but I would have to generate hundreds of (unecassary) span-elements as I don't know the maximum width of the element.

The idea is very simply: Dots that don't fit, float into the hidden overflow.

Source

HTML

<ul>
  <li>
    <div>
      <span></span><span></span><span></span><span></span><span></span><span></span>
    </div>
    Item 1
  </li>
  <li>
    <div>
      <span></span><span></span><span></span><span></span><span></span><span></span>
    </div>
    Item 2
  </li>
</ul>

CSS

ul {
  margin: 0;
  padding: 0;
  list-style: none;
  line-height: 60px;
}

ul > li div {
  overflow: hidden;
  height: 2px;
}

ul > li div span {
  float: left;
  width: 2px;
  height: 2px;
  margin: 0 4px 0 0;
  background: grey;
}

JSFiddle

You can try it here

Is there a classy way to solve this, like using some nice SVG- or gradient-trick?

like image 938
lampshade Avatar asked Feb 07 '23 04:02

lampshade


2 Answers

border-image seems like the way to go to me. You can control the size, and specify that the repeats be rounded to your desired width.

li {
  font-size: 40px;
}

.small {
  border: solid transparent;
  border-width: 15px 0 0;
  border-image:url("https://mdn.mozillademos.org/files/4127/border.png") 27 27 round;
}

.large {
  border: solid transparent;
  border-width: 30px 0 0;
  border-image:url("https://mdn.mozillademos.org/files/4127/border.png") 27 27 round;
}
<ul>
  <li class="small">First list item</li>
  <li class="large">Second list item</li>
</ul>

I've used a diamond-form PNG from the MDN site here, but you should be able to create a PNG (or SVG) with your desired dot shape easily enough.

like image 76
Paul LeBeau Avatar answered Feb 13 '23 06:02

Paul LeBeau


Here is an example using svg :

function getCenterDotPosition( position, dotWidth ) {
  return ( dotWidth / 2 ) + ( position ) * dotWidth * 2;
}
function getRightPosition( position, dotWidth ) {
  return getCenterDotPosition( position, dotWidth ) + dotWidth/2;
}

function getSVG( options ) {
  var width = options.width;
  var height = options.dotWidth;
  var svg = '<svg class="top-dot" width="' + width + 'px" height="' + height + 'px">';
  var left;
  var radius = options.dotWidth / 2;
  var i = 0;
  var right = getRightPosition( i, options.dotWidth );
  while( right < width ) {
    center = getCenterDotPosition( i, options.dotWidth );
    svg += '<circle cx="' + center + '" cy="' + radius + '" r="' + radius + '" stroke="none" stroke-width="0" fill="' + options.color + '" />';
    i++;
    right = getRightPosition( i, options.dotWidth );
  }
  svg += '</svg>';
  return svg;
}

function generateDots() {
  var options = {
    width    : $('ul').first().innerWidth(),
    dotWidth : 2,
    color    : 'grey'
  };
  var svg = getSVG( options );
  $( 'li svg.top-dot' ).remove()
  $( 'li' ).prepend( svg ); 
}


generateDots();
$( window ).resize(function() {
  generateDots();  
});
ul {
  margin: 0;
  padding: 0;
  list-style: none;
  line-height: 60px;
  width: 50%;
}

svg.top-dot {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
</ul>
like image 40
Toumtam Avatar answered Feb 13 '23 07:02

Toumtam