Mihkel Allorg
Mihkel Allorg

Reputation: 989

Dot leaders with picture background

So I'm building a website for a restaurant and I'm in a pickle. I'm trying to create the menu there. The idea is to align the food name to the left, the price to the right and fill the gap between them with dots. Like this

Hamburger ............................................ $ 4.00

XXL Hamburger .................................... $ 4.00

Milkshake .............................................. $ 4.00

I found a couple of solutions, which only work if you have a background with one color and no texture. The idea was to fill the whole line with dots and set the name/price background span with the same color as the site background, so the dots wouldn't show. But I have a picture for the background.

I'm not going to post my code here, because it wouldn't really matter or help.

Is it even possible? Doesn't have to be css only, might as well be done with JavaScript.

Upvotes: 4

Views: 710

Answers (6)

Joshua Michael Calafell
Joshua Michael Calafell

Reputation: 3107

Use a div that has a flex spacer with a border-bottom to achieve easy leader dots... The flex layout seems to be the most elegant solution. No pseudo-elements, or left and right block display, etc... Very simple...

HTML

<div class="list-item">

    <div class="header-row">
      <h4>Menu</h4>
    </div>

    <br>

    <div class="list-item-row">
      <div class="left">Hamburger</div>
      <div class="dots"></div>
      <div class="right">$5.00</div>
    </div>

    <div class="list-item-row">
      <div class="left">Hamburger (XXL)</div>
      <div class="dots"></div>
      <div class="right">$7.50</div>
    </div>

    <div class="list-item-row">
      <div class="left">Milkshake</div>
      <div class="dots"></div>
      <div class="right">$3.50</div>
    </div>

    <div class="list-item-row">
      <div class="left">Pickle</div>
      <div class="dots"></div>
      <div class="right">Free</div>
    </div>

</div>

CSS

@import url("https://fonts.googleapis.com/css?family=Lato|Montserrat:400,700|Roboto:400,700");

* {
  margin: 0;
  padding: 0;
}

button {
  font-family: "Roboto";
  font-size: 16px;
  padding: 5px;
  border-radius: 3px;
  border: solid #424242 1px;
}

.list-item {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-start;
  margin: 20px;
  font-family: "Lato";
  background: #f0f0f0;
  padding: 10px;
  border: solid #e0e0e0 1px;
}

.list-item-row,
.header-row {
  width: 100%;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  .left,
  .right {
    font-family: "Roboto";
  }
  .right {
    color: blue;
  }
}

.dots {
  flex: 1 0 0;
  border-bottom: dotted 2px #b0b0b0;
  margin-left: 1em;
  margin-right: 1em; 
}

See Codepen here => https://codepen.io/anon/pen/vVZmxB

Upvotes: 0

mattbru
mattbru

Reputation: 11

Thanks. I used what you had here and improved on it. This code is meant for woocommerce product items, but can be edited for whatever you need. $containerElement is the element you are measuring the width of.

/**
 * dotFiller
 * adds dynamic dot leaders between product title and count element (<mark>)
 * @return void
 */
var dotFiller = function(){
    var $containerElement = $('ul.products li.product.has-children h2'),
        df  = '<div class="df">.....................................................................</div>';
        $containerElement.each(function(i,el){
                var $el = $(el),
                    w   = $el.width(),
                    mw  = $el.find('mark').width(),
                    tw  = $el.find('span').width(),
                    dfw = (w - mw - tw) - 24;
                // if its not there, lets add it
                if (!$(el).has('.df').length){
                    $el.find('span').after(df);
                }
                $el.find('.df').css('width',dfw + "px");
        });
};
dotFiller();

With this code, you can update/ recalculate on resize like so :

$('window').on('resize',function(){ dotFiller(); });

And here is my css for the internal elements:

        mark {
            background-color: transparent;
            color: $secondary;
            display: inline-block; float: right;
            font-weight: normal;
        }
        div.df { 
            overflow: hidden; 
            display: inline-block; 
            margin-left: 10px; 
            position: relative; 
            top: 2px; 
            font-weight: normal; 
            opacity: 0.8; 
        }

I hope this helps someone!

Upvotes: 0

Jacob G
Jacob G

Reputation: 14172

I am kinda late, but you can quite easily do it with a radial-gradient:

.col {
  display: inline-block;
  vertical-align: top;
}

.names span {
  width: 200px;
  display: flex;
}

.prices span {
  display: block;
  text-align:right;
}

.names span:after {
  content: "";
  display: inline-block;
  height: 1em;
  flex-grow: 1;
  background: radial-gradient(black 25%, transparent 25%) scroll repeat-x bottom left/5px 5px;
}
<div class='names col'>
  <span>Hamburger</span>
  <span>Hot Dogs</span>
  <span>Superman Hamburger</span>

</div>
<div class='prices col'>
  <span>$1.00</span>
  <span>$0.50</span>
  <span>$400.00</span>
</div>

JSFiddle Demo

Upvotes: 2

herrh
herrh

Reputation: 1368

Use display:table; and display: table-cell; for the divs inside the list-elements and border-bottom: Xpx dotted black; for the dots.

ul{
  margin: 0;
  padding: 0;
}
ul li{
  display: table;
  width: 100%;
}
ul li div {
  display: table-cell;
}
ul li div.food {
  padding-right: 5px;
}
ul li div.dots {
  border-bottom: 1px dotted #000;
  width: 100%;
  position: relative;
  top: -4px;
}
ul li div.price {
  padding-left: 5px;
}
<ul>
  <li>
    <div class="food">Spaghetti</div>
    <div class="dots">&nbsp;</div>
    <div class="price">10.00$</div>
  </li>
  <li>
    <div class="food">Spaghetti</div>
    <div class="dots"></div>
    <div class="price">10.00$</div>
  </li>
  <li>
    <div class="food">Spaghetti</div>
    <div class="dots"></div>
    <div class="price">10.00$</div>
  </li>
</ul>

Upvotes: 1

Rob Louie
Rob Louie

Reputation: 2671

It's easy to do with some simple javascript and css, here's a fiddle: jsfiddle

The key is to set the width of the div that holds the dots to the width of the column minus the width of the food name minus the width of the price, and to make sure there are more than enough dots to cover the distance, and to set overflow: hidden for the dot div.

$(".menu-row").each(function(index, element) {
    var menuRowWidth = $(element).width();
    var foodItemWidth = $(element).children('.food-item').width();
    var priceWidth = $(element).children('.price').width();
    var $dotFiller = $(element).children('.dot-filler');
    var dotFillerWidth = menuRowWidth - foodItemWidth - priceWidth;
    $dotFiller.width(dotFillerWidth + "px"); 
});

Then float the item and dot div left, the price right, all within a set width column. It's also important that overflow: hidden is set for the dots, because when we set the width of that div in javascript we want all extra dots to just be cut off. The CSS:

.food-item {
  float: left
}

.dot-filler {
  overflow: hidden;
  width: 0;
  float: left;
}

.price {
  float: right;
}

.menu-row {
  width: 400px;
}

Then structure your html as follows:

<div class="menu-row">
  <div class="food-item">Steak</div>
  <div class="dot-filler">............................................................................................</div>
  <div class="price">$18.00</div>
</div>

<div class="menu-row">
  <div class="food-item">Hamburger</div>
  <div class="dot-filler">............................................................................................</div>
  <div class="price">$8.00</div>
</div>

Upvotes: 1

Ziv Weissman
Ziv Weissman

Reputation: 4526

You can use a wrapper to set a fix width of your Name + Dots.

The css will look like this:

.wrapper {
  width: 300px;
  overflow: hidden;
  display: inline-block;;
  white-space: nowrap;
}

The HTML like this:

<div>
  <ul class="noDisc">
    <li>
      <div class="wrapper">
      <span>HAMBURGER </span>
      <span>...............................................................</span>
      </div>
      <span>$ 40.00</span>
    </li>
     <li>
      <div class="wrapper">
      <span>FRIED CHIKEN </span>
      <span>...............................................................</span>
      </div>
      <span>$ 13.00</span>
    </li>
     <li>
      <div class="wrapper">
      <span>STEAK ON A STICK </span>
      <span>...............................................................</span>
      </div>
      <span>$ 99.00</span>
    </li>
  </ul>
</div>

Live sample:

fiddle

Upvotes: 1

Related Questions