jQuery: Toggleable path-like navigation with decorations - javascript

This is my code:
$("#one_link").click(function() {
$("#categories").toggle();
$(this).toggleClass("active"); //Active class
$(this).prepend("▶ "); //Should toggle and not insert over and over again
$("#text_three").hide();
$("#cats_text").hide();
$("#text_two").hide();
});
$("#cats_link").click(function() {
$("#cats_text").toggle();
$(this).toggleClass("active"); //Active class
$(this).prepend("▶ "); //Should toggle and not insert over and over again
$("#text_two").hide();
$("#text_three").hide();
});
$("#two_link").click(function() {
$("#text_two").toggle();
$(this).toggleClass("active"); //Active class
$(this).prepend("▶ "); //Should toggle and not insert over and over again
$("#categories").hide();
$("#cats_text").hide();
$("#text_three").hide();
});
$("#three_link").click(function() {
$("#text_three").toggle();
$(this).toggleClass("active"); //Active class
$(this).prepend("▶ "); //Should toggle and not insert over and over again
$("#categories").hide();
$("#cats_text").hide();
$("#text_two").hide();
});
* {
list-style-type: none;
margin: 0;
padding: 0;
font-size: 30px;
line-height: 100%;
cursor: default;
font-family: Arial;
}
html,
body {
width: 100vw;
height: 100vh;
overflow: hidden;
}
.content {
display: flex;
overflow: hidden;
width: 100vw;
height: 100vh;
}
.column {
border-right: 1px solid black;
}
.column_content {
overflow-y: scroll;
width: 100%;
height: 100%;
padding: 20px;
}
.column {
display: none;
}
.column:first-child {
display: block;
}
li:hover {
cursor: pointer;
}
.active {
text-decoration: underline yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<div class="column">
<div class="column_content">
<ul>
<li id="one_link">One</li>
<li id="two_link">Two</li>
<li id="three_link">Three</li>
</ul>
</div>
</div>
<div id="categories" class="column">
<div class="column_content">
<ul>
<li id="cats_link">Cats</li>
</ul>
</div>
</div>
<div class="column" id="cats_text">
<div class="column_content">
<p>The cat (Felis catus) is a domestic species of small carnivorous mammal. It is the only domesticated species in the family Felidae and is often referred to as the domestic cat to distinguish it from the wild members of the family.</p>
</div>
</div>
<div class="column" id="text_two">
<div class="column_content">
<p>2 (two) is a number, numeral, and glyph. It is the natural number following 1 and preceding 3. It is the smallest and only even prime number. Because it forms the basis of a duality, it has religious and spiritual significance in many cultures.</p>
</div>
</div>
<div class="column" id="text_three">
<div class="column_content">
<p>3 (three) is a number, numeral, and glyph. It is the natural number following 2 and preceding 4, and is the smallest odd prime number. It has religious or cultural significance in many societies.</p>
</div>
</div>
</div>
If you click only »One« and then »Cats«, it looks exactly how it should be.
But if you click then for example »Two« or »Three«, then »One« has still a text-decoration. This shouldn't happen, it should also toggle.
Furthermore, the »▶« should be a part of this marking. It should be inserted at most once before each link.
Ah and I will need more categories, so it would be great if it were easily expandable.
Can someone help me?
Would be very happy! :)

Can't say that this is perfect, but I made some improvements.
For starters I cut down on the amount of repetitive Javascript by leveraging HTML attributes like class and some data-*
See: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-*
Also note that I moved your ▶ into a pseudo element on the active class.
See: https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements
$('.tab-opening-button').click(function(){
const openId = $(this).attr('data-open');
const linkParent = $(this).attr('data-parent-link');
if(!linkParent){
$('#categories').hide();
}
$('.text-panel').hide();
$(openId).show();
$('.tab-opening-button').not(linkParent).removeClass('active');
$(this).addClass('active');
});
* {
list-style-type: none;
margin: 0;
padding: 0;
font-size: 30px;
line-height: 100%;
cursor: default;
font-family: Arial;
color: rgb(80, 80, 80);
box-sizing: border-box;
}
html,
body {
width: 100vw;
height: 100vh;
overflow: hidden;
}
.content {
display: flex;
overflow: hidden;
width: 100vw;
height: 100vh;
}
.column {
border-right: 3px solid;
flex-shrink: 0;
}
.text-panel {
flex-shrink: 1;
}
.column_content {
overflow-y: auto;
width: 100%;
height: 100%;
padding: 20px;
}
.column {
display: none;
}
.column:first-child {
display: block;
}
li:hover {
cursor: pointer;
}
.active {
text-decoration: underline yellow;
}
.active:before {
content: "▶ "
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="content">
<div class="column">
<div class="column_content">
<ul>
<li data-open="#categories" class="tab-opening-button" id="one_link">One</li>
<li data-open="#text_two" class="tab-opening-button" id="two_link">Two</li>
<li data-open="#text_three" class="tab-opening-button" id="three_link">Three</li>
</ul>
</div>
</div>
<div id="categories" class="column">
<div class="column_content">
<ul>
<li data-open="#cats_text" data-parent-link="#one_link" class="tab-opening-button" id="cats_link">Cats</li>
</ul>
</div>
</div>
<div class="column text-panel" id="cats_text">
<div class="column_content">
<p>The cat (Felis catus) is a domestic species of small carnivorous mammal. It is the only domesticated
species in the family Felidae and is often referred to as the domestic cat to distinguish it from the
wild members of the family.</p>
</div>
</div>
<div class="column text-panel" id="text_two">
<div class="column_content">
<p>2 (two) is a number, numeral, and glyph. It is the natural number following 1 and preceding 3. It is the
smallest and only even prime number. Because it forms the basis of a duality, it has religious and
spiritual significance in many cultures.</p>
</div>
</div>
<div class="column text-panel" id="text_three">
<div class="column_content">
<p>3 (three) is a number, numeral, and glyph. It is the natural number following 2 and preceding 4, and is
the smallest odd prime number. It has religious or cultural significance in many societies.</p>
</div>
</div>
</div>

Related

Creating multiple Modals for many different pictures

I have a modal that contains many different items(Menu items). I want to make it so when I click the heading of any specific menu item, another modal pops-up showing the image of said dish. The only issue I run into, is that I would have to create a ton of different modals for each item dish(15 of them). IS there a way I can create a function/loop fthem so they only access a soecific image attatched to said item? Should I create a seperate container for the images? Or add them to the item containers themselves and set the display to none?
Here is an example without much css or the JS with it? Any thoughts of the best way to tackle this?
/*This is the background/ not the box itself*/
.menu {
display: block;
position: fixed;
z-index: 999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: none;
background-color: rgba(0, 0, 0, .4);
}
/*Menu Content Box*/
.menuContent {
background-color: #f1e3cb;
margin: 5% auto;
border: 1px solid #888;
width: 50%;
height: 80%;
border-radius: 5px;
font-family:'IM Fell French Canon SC', serif;
font-weight: 600;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 10px;
}
&::-webkit-scrollbar-track {
background: #f1e3cb;
}
&::-webkit-scrollbar-thumb {
background: #888;
}
.menuHeader {
text-align: center;
}
.menu-items {
display: flex;
flex-direction: row;
justify-content: space-evenly;
text-align: center;
margin: 20px 0 0;
> div {
width: 33%;
margin: 0 5px;
}
p{
text-align: left;
&:hover {
cursor: pointer;
transform: scale(1.1);
transform-origin: left;
}
}
.item {
margin-top: 20px;
align-self: center;
}
}
}
/*Close button*/
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
padding-right: 10px;
overflow: auto;
&:hover,
&:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
}
<!--Menu Modal-->
<div id="myMenu" class="menu">
<!--Menu Content-->
<div class="menuContent">
<span class="close">×</span>
<div class="menuHeader">
<h1>Menu</h1>
</div>
<div class="menu-items">
<div class="Appetizers">
<h2>Appetizers</h2>
<div class="item">
<p>Sardine canapés:</p>
<small>Roasted sardines, boiled egg yolk, whole olives, and a choice of cheese stacked
on our signature house bread.
</small>
</div>
<div class="item">
<p>Crab Stuffed with Crayfish:</p>
<small>Fried crab and vegetables stuffed into large crayfish.</small>
</div>
<div class="item">
<p>Shrimp Canapés:</p>
<small>Lemon fried shrimp, cucumber slicies atop house bread served with a side of
our shrimp sauce.
</small>
</div>
<div class="item">
<p>Préfou:</p>
<small>House baguette stuffed with garlic butter and parsely.</small>
</div>
<div class="item">
<p>Moules farcies:</p>
<small>baked mussels stuffed with garlic butter, parsley, shallots and nutmeg. Topped with
parmesan cheese and breadcrumbs .
</small>
</div>
</div>
<div class="Entrees">
<h2>Entrees</h2>
<div class="item">
<p>Lamb chops & Cognac dijon:</p>
<small>Juicy lamb elegantly served with our signature Dijon sauce</small>
</div>
<div class="item">
<p>Chicken Cordon Bleu:</p>
<small>Chicken stuffed with ham and cheese sauce, served atop a bed of roasted lettuce.</small>
</div>
<div class="item">
<p>Coq au vin:</p>
<small>Chicken drums braised with wine, mushrooms, pork and garlic butter. Topped with
green onion and chili, and a side of roasted scallops.
</small>
</div>
<div class="item">
<p> Ratatouille:</p>
<small>Award winning dish. Shallow fried vegetables layered in our signature baked casserole.
</small>
</div>
<div class="item">
<p>Roast Chicken:</p>
<small>Cuts of chicken roasted in garlic butter and an herby crust served with roasted baby spinach.</small>
</div>
<div class="item">
<p>Duck a l'orange:</p>
<small>Duck legs and breast served with fresh orange sauce.</small>
</div>
<div class="item">
<p>Croque-Monsieur:</p>
<small>Baked ham and cheese with velvety bechamel. Served with egg upon request.</small>
</div>
</div>
<div class="Desserts">
<h2>Desserts</h2>
<div class="item">
<p>Apricot and Almond Galette:</p>
<small>Fruity galettes stuffed with an almond cream.</small>
</div>
<div class="item">
<p>Honey Hazelnut Financiers:</p>
<small>Buttery brown cakes tops with a berry-hazelnut topping.</small>
</div>
<div class="item">
<p>Caramelized-Honey Brulee:</p>
<small>House Brulee coated with a caramelized layer of torched honey.</small>
</div>
</div>
</div>
</div>
You don't need a separate modal for each image. You just need a one modal that will display different images.
Using javascript, you need to add a click event listener to the container of all the items. When any items is clicked, get the src attribute of the img element associated with that item and set this src attribute as the src attribute of the img in the modal.
Here's a demo in which i have 3 images which are displayed in a modal one at a time depending on which image label you clicked on.
const modal = document.getElementById('modal');
const modalContainer = document.querySelector('.modal-container');
const container = document.getElementById('container');
container.addEventListener('click', (event) => {
if (event.target.matches('span')) {
const src = event.target.nextElementSibling.getAttribute('src');
modal.children[0].setAttribute('src', src);
modalContainer.classList.add('showModal');
}
});
modalContainer.addEventListener('click', () => {
modalContainer.classList.remove('showModal');
})
body { margin: 0; }
img { display: none; }
div span {
display: inline-block;
margin: 5px;
font-size: 1.2rem;
cursor: pointer;
text-decoration: underline;
color: blue;
}
.modal-container {
display: none;
position: fixed;
background: #222;
width: 100vw;
height: 100vh;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.8);
}
.modal-container img { display: inline-block; }
.showModal { display: flex; }
<div class="modal-container">
<div id="modal">
<img src="" />
</div>
</div>
<div id="container">
<div>
<span>Show Image 1</span>
<img src="https://picsum.photos/id/1/200/" />
</div>
<div>
<span>Show image 2</span>
<img src="https://picsum.photos/id/20/200/" />
</div>
<div>
<span>Show image 3</span>
<img src="https://picsum.photos/id/30/200/" />
</div>
</div>

How to use <ul> to display scrolling contents?

I came across https://minimill.co/ and saw it as a good example to what I'm trying to achieve.
I made an attempt to display the listed items like the site:
.wrap {
display: block;
list-style: none;
position: relative;
padding: 0;
margin: 0;
border: 0;
li {
background-color: green;
}
}
.content {
margin: 0 auto;
max-width: 66rem;
width: 90%;
padding: 0;
border: 0;
position: relative;
}
.right-details {
display: inline-block;
float: right;
box-size: border-box;
width: 33.33333%;
}
.left-img {
display: inline-block;
float: left;
box-sizing: border-box;
width: 66.66666%;
img {
width: 50px;
}
}
<ul class="wrap">
<li>
<div class="content">
<div class="left-img">
<img src="/assets/img/macbook-image.png"/>
</div>
<h2 class="right-details">
Item 1
</h2>
</div>
</li>
<li>
<div>
<h2>
Item 2
</h2>
</div>
</li>
</ul>
But the first <li> disappears.
How can I display my contents in one long scroll-like how https://minimill.co/ is doing? Am I doing it correctly as implemented on the site? Any guidance or insight on mimicking it more closely would be appreciated.
You should use min-height:100vh instead of height:100vh;. Please check my fiddle
// select all elements with data-background attribute
var lis = document.querySelectorAll("[data-background]");
// create empty array
var heights = [];
// use for loop to "discover" all of the elements in lis array
for(var i = 0; i < lis.length; i++){
// get element's distance from top
var distanceFromTop = lis[i].offsetTop;
// get value from data-backgrount attribute
var background = lis[i].getAttribute("data-background");
// push background and distance to heights array
heights.push({background: background, distance: distanceFromTop});
};
// check if page was scrolled
window.addEventListener("scroll", function(evt){
// if page was scrolled what's the user's distance from top
var distanceFromTop = this.scrollY;
// find distances in heights array
heights.forEach(function(height) {
// check if user reached another checkpoint
if(height.distance < distanceFromTop) {
// if so, change the background to value that we got from data-background attribute
//
document.body.className = height.background;
}
});
});
body {
transition: background-color .8s ease;
-webkit-transition: background-color .8s ease;
}
body.blue { background-color: #39f; }
body.red { background-color: #FF351A; }
body.dark { background-color: #222; }
body.yellow { background-color: #fd3; }
body.deep-blue { background-color: #417ABA; }
body.white { background-color: #fff; }
body.beige { background-color: #F7D693; }
li {
min-height: 100vh;
list-style-type:none;
}
<body class="blue">
<ul>
<li data-background="blue"></li>
<li data-background="red"></li>
<li data-background="dark"></li>
<li data-background="yellow"></li>
<li data-background="deep-blue"></li>
<li data-background="white"></li>
<li data-background="beige"></li>
</ul>
</body>
You should use min-height:100vh instead of height:100vh;. Please check my fiddle
So easiest approach seems to be using height: 100vh;, which stands for hundredths of the viewport height. (see: quirksmode.org).
body, ul, li {
height: 100%;
}
li { height: 100vh; }
ul { list-style-type: none; }
.a { background-color: red; }
.b { background-color: yellow; }
.c { background-color: black; }
.d { background-color: green; }
.e { background-color: orange; }
.f { background-color: pink; }
<body>
<ul>
<li class="a"></li>
<li class="b"></li>
<li class="c"></li>
<li class="d"></li>
<li class="e"></li>
<li class="e"></li>
</ul>
</body>
But: it is not supported for IE <= 10 and Android <= 4.3.
(see: caniuse).
What minimill does on their website is using two <ul> tags:
<ul class="backgrounds"> which has it's position: fixed (love self-descriptive class names);
<ul class="sections"> which stores actual content of the web site;
and the key to make it all work: .sections li with padding: 16rem 0 0; (which means: padding-top: 16rem;). It is all customized to the need of images they use.
See here:
body, li, ul { /* RESET */
margin: 0;
padding: 0;
border: 0;
font: inherit;
vertical-align: baseline;
}
html, body { height: 100%; }
body {
line-height: 1.5;
position: relative;
}
ul { list-style-type: none; }
.backgrounds {
height: 100%;
display: block;
bottom: 0;
left: 0;
position: fixed;
right: 0;
top: 0;
z-index: 1;
}
.backgrounds li {
height: 100%;
left: 0;
opacity: 0;
position: absolute;
top: 0;
transition: .5s ease opacity;
width: 100%;
z-index: 1;
}
.sections {
position: relative;
transition: .5s ease opacity;
z-index: 2;
}
.sections li { padding: 16rem 0 0; }
.a { background-color: red; }
.b { background-color: yellow; }
.c { background-color: black; }
.d { background-color: green; }
.e { background-color: orange; }
.f { background-color: pink; }
<body>
<ul class="backgrounds">
<li class="a"></li>
<li class="b"></li>
<li class="c"></li>
<li class="d"></li>
<li class="e"></li>
<li class="f"></li>
</ul>
<ul class="sections">
<li class="a"><p>Lorem ipsum dolor sit amet;</p></li>
<li class="b"><p>Lorem ipsum dolor sit amet;</p></li>
<li class="c"><p>Lorem ipsum dolor sit amet;</p></li>
<li class="d"><p>Lorem ipsum dolor sit amet;</p></li>
<li class="e"><p>Lorem ipsum dolor sit amet;</p></li>
<li class="f"><p>Lorem ipsum dolor sit amet;</p></li>
</ul>
</body>
Furthermore, all the background swaping is made with JS.
Based on the example you provided, the first list item should be height: 100vh; and the height of the other items will be based on the content itself. In the code below, I added a bit of script that scrolls from the first item to the second when the "Scroll Down" anchor tag is clicked.
Check out my jsfiddle.
Here's the HTML:
<ul id="wrap">
<li>
<div>
<h2>Item 1</h2>
<div id="scroll-down">
Scroll Down
</div>
</div>
</li>
<li id="scrollto">
<div>
<h2>Item 2</h2>
</div>
</li>
<li>
<div>
<h2>Item 3</h2>
</div>
</li>
</ul>
Here's the SCSS:
$width: 100%;
$height: 100%;
html, body {
width: $width;
height: $height;
margin: 0;
padding: 0;
}
#wrap {
display: inline-block;
list-style: none;
padding: 0;
margin: 0;
width: $width;
height: $height;
li {
display: block;
overflow: hidden;
position: relative;
width: $width;
}
li:first-child {
background-color: green;
height: 100vh;
}
li:not(:first-child) {
min-height: 400px;
}
li:nth-child(2) {
background-color: lightgreen;
}
li:last-of-type {
background-color: lightblue;
}
}
h2 {
margin-top: 0;
}
#scroll-down {
position: absolute;
bottom: 15px;
width: $width;
}
#scroll-down a {
display: block;
text-align: center;
color: #ffffff;
}
Here's a bit of JQuery:
$(document).ready(function(){
$("#scroll-down").click(function() {
$('html, body').animate({
scrollTop: $("#scrollto").offset().top
}, 1000);
});
});
What you are looking at https://minimill.co/ is in fact two ul's, one is being used to show the background color and the other is used to show the content. It seems that the ul associated with the background color does have a javascript event listener that tracks your the window scroll and depending on what content is being shown, the corresponding background color is displayed.
Yes, you are on the right path. In fact, this particular page has a very large top padding (16rem = 16 * 16px = 256px) to centralize the content and depending on the window size, it has different css classes.
Regarding your question, I did try it and the first item appears to me.
It depends on what from Minimill's site, that you want to achieve. Minimill does have that fancy background-color-change, which is an event-listener - but it sounds like, that you just want to have the sections as they do?
Such as:
Section about: We are Minimill
Section about: Redspread
Section about: KPCB
...
...
If it's just that you want to have sections in the same way, then that can achieve quite easily. If you haven't heard of it, then I would point you in the direction of Bootstrap which is a CSS-library that does A LOT for you. When I first heard of it, then I thought 'That sounds like a hassle to look into', - but it's really quite magical, how much time you save by spending a couple of hours understanding how it works.
You can also code the whole thing yourself, such as: https://jsfiddle.net/2awczzcc/2/
And here's the code:
<ul class="wrap">
<li>
<div class="content">
<div class="left-container">
<img src="http://vignette2.wikia.nocookie.net/fantheories/images/4/43/Toy-Story-Theme-Song-6.jpg/revision/latest?cb=20140624192735"/>
</div>
<div class="right-container">
<h2>
Item 1
</h2>
<p>
Text text text.
</p>
</div>
</div>
</li>
<li>
<div class="content">
<div class="left-container">
<img src="http://vignette2.wikia.nocookie.net/fantheories/images/4/43/Toy-Story-Theme-Song-6.jpg/revision/latest?cb=20140624192735"/>
</div>
<div class="right-container">
<h2>
Item 2
</h2>
<p>
Text text text.
</p>
</div>
</div>
</li>
<li>
<div class="content">
<div class="left-container">
<img src="http://vignette2.wikia.nocookie.net/fantheories/images/4/43/Toy-Story-Theme-Song-6.jpg/revision/latest?cb=20140624192735"/>
</div>
<div class="right-container">
<h2>
Item 2
</h2>
<p>
More text, more text, more text.
</p>
</div>
</div>
</li>
</ul>
And the CSS:
.wrap {
display: block;
list-style: none;
position: relative;
padding: 0;
margin: 0;
border: 0;
width: 100%;
}
.wrap li {
width: 100%;
clear: both;
display: block;
min-height: 200px;
float: left;
margin: 0;
padding: 0;
}
.wrap li:first-child {
background-color: green;
}
.wrap li:nth-child(2) {
background-color: blue;
}
.wrap li:nth-child(3) {
background-color: yellow;
}
.content {
margin: 0 auto;
max-width: 66rem;
width: 90%;
padding: 0;
border: 0;
position: relative;
}
.left-container {
float: left;
width: 48%;
overflow: hidden;
}
.right-container {
float: right;
width: 48%;
overflow: hidden;
}
.left-container img {
display: inline-block;
float: left;
box-sizing: border-box;
max-width: 100%;
height: auto;
margin: 25px 0 0 0;
}
Link to jsFiddle
HTML Code:
<ul>
<li id="one" data-color="#16A085">
<h2>Section One</h2>
</li>
<li id="two" data-color="#C0392B">
<h2>Section Two</h2>
</li>
<li id="three" data-color="#ff44AD">
<h2>Section Three</h2>
</li>
<li id="four" data-color="#f88f18">
<h2>Section Four</h2>
</li>
<li id="five" data-color="#E91E63">
<h2>Section Five</h2>
</li>
</ul>
Javascript
$(window).on("scroll touchmove", function() {
if ($(document).scrollTop() >= $("#one").position().top) {
$('body').css('background', $("#one").attr("data-color"));
};
if ($(document).scrollTop() > $("#two").position().top) {
$('body').css('background', $("#two").attr("data-color"))
};
if ($(document).scrollTop() > $("#three").position().top) {
$('body').css('background', $("#three").attr("data-color"))
};
if ($(document).scrollTop() > $("#four").position().top) {
$('body').css('background', $("#four").attr("data-color"))
};
if ($(document).scrollTop() > $("#five").position().top) {
$('body').css('background', $("#five").attr("data-color"))
};
});
CSS
li {
display: block;
width: 100%;
height: 100vh;
}
body {
background: #16A085;
color: #fff;
margin: 0;
transition: all 550ms ease;
will-change: background;
}
All you have to do is add height: 100vh; to the style for LI and you should be set.
Working codepen (I had to modify the CSS a bit since codepen doesn't support sass).
If I misunderstood the question and that's not what you're looking for, let me know.
You can set the height of ul or your div.
Also, set overflow to auto:
<ul style="width: 300px; height: 200px; overflow: auto">
<li>items</li>
<li>items</li>

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.
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
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>
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
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"> </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>
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!
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

How to wrap more than one div around a div

I have a div (Slideshow) and I want to wrap around it small divs (Items). The Slideshow div will be static and the Items will be rendered automatically using a Repeater Control.
I made this image to better illustrate what I need to achieve.
I saw this Question and I thought I could use the same logic, let the Repeater items get rendered normally and then change the markup using JavaScript and use some sort of a CSS Grid layout to style the first 4 items for example on the left and the right and the rest will be beneath them but I'm not sure how to do it plus if there's a more simple solution I thought it could be cleaner than using the concept I saw in the question I referred.
Update1: Changed the picture to show the exact desired output
You could generate a Masonary layout. This plug in may be helpful, https://github.com/desandro/masonry
You could do this with bootstrap columns as well. For the first row, with the slideshow, you have 3 columns. The outer left and right columns will have 2 nested rows. http://getbootstrap.com/examples/grid/. This is what Im most familiar with so I'll show you how I would implement a solution for the first row and how to implement a second row with 4 columns.
<div class="row">
<!-- Outer Left Column -->
<div class="col-xs-4">
<div class="row">
<div class="col-xs-12">
Item
</div>
</div>
<div class="row">
<div class="col-xs-12">
Item
</div>
</div>
</div>
<div class="col-xs-12">
Slide Show
</div>
<!-- Outer Right Column -->
<div class="col-xs-4">
<div class="row">
<div class="col-xs-12">
Item
</div>
</div>
<div class="row">
<div class="col-xs-12">
Item
</div>
</div>
</div>
</div>
<!-- Row With Four Items -->
<div class="row">
<div class="col-xs-3">
Item
</div>
<div class="col-xs-3">
Item
</div>
<div class="col-xs-3">
Item
</div>
<div class="col-xs-3">
Item
</div>
</div>
Checkout the angular material layout system as well. This will be harder to implement though because it requires Angular. https://material.angularjs.org/latest/#/layout/grid
Check this solution out and see if you can adopt it to your project: http://jsfiddle.net/1b0hoked/.
HTML:
<div id = "wrapper">
<div id = "slideshow"></div>
</div>
CSS:
*, :before, :after {
margin: 0;
padding: 0;
border: 0;
box-sizing: border-box;
}
body {
padding: 10px;
}
#wrapper {
counter-reset: item-counter;
text-align: right;
margin: 0 auto;
display: table;
outline: 1px solid gray;
position: relative;
}
#slideshow {
width: 210px;
height: 210px;
line-height: 210px;
text-align: center;
border: 2px solid red;
position: absolute;
top: 5px;
left: 50%;
margin-left: -105px;
}
#slideshow:before {
content: "Slide Show";
vertical-align: middle;
font: bold 16px/1 Sans-Serif;
color: red;
}
.item {
height: 100px;
width: 100px;
text-align: center;
line-height: 96px;
border: 2px solid #aaa;
}
.item:before {
counter-increment: item-counter;
content: "item " counter(item-counter);
vertical-align: middle;
font: bold 12px/1 Sans-Serif;
color: #aaa;
}
.item {
float: left;
margin: 5px;
}
.item:nth-of-type(4n + 1) {
clear: left;
}
.item:nth-of-type(3) {
float: right;
margin-top: -105px;
}
.item:nth-of-type(4) {
float: right;
clear: right;
margin-left: -105px;
}
.item:nth-of-type(2) {
clear: left;
}
JS/jQuery:
$(function() {
var numToAdd = 50;
while(--numToAdd >= 0) {
$("</p>").addClass("item").appendTo("#wrapper");
}
});

Centralising nested Divs which have onclick elements

I have 2 rows, one which needs two images and the other which needs to show information if those images are clicked.
I'm having an issue centralising the images and text within the row div.
<div id="container">
<!-- Image row -->
<div class="row">
<div class="col-md-6">
<div id="badbutton"></div>
</div>
<div class="col-md-6">
<div id="goodbutton"></div>
</div>
</div>
<!-- Text Row -->
<div class="row">
<div class="col-md-6">
<div id="bad" style="display:none;">
<p>Oh no! We'd appreciate it if you'd share your experience with us so we can improve in the future. Just click below to get started.</p>
<p> FORM HERE </p>
</div>
</div>
<div class="col-md-6">
<div id="good" style="display:none;">
<p>Fantastic! Please share your experience with the world on of these popular websites. Just make a selection below to get started.</p>
<ol>
<li>Click here to review us on Google+ Reviews</li>
<li>Click here to review us on Facebook</li>
</ol>
</div>
</div>
</div>
</div>
What's happening is the col-md-6 takes up 45% of the row div but the buttons inside aren't centralising themselves.
Here is the CSS:
.row {
margin: 0 auto;
}
.col-md-6 {
position: relative;
min-height: 1px;
padding-right: 15px;
padding-left: 15px;
}
.col-md-6 {
width: 45%;
}
#good,
#bad {
width: 50%;
}
Here is the outcome:
Try using display:table-* it will make your elements behavior like a table.
.row {
margin: 0 auto;
display: table-row;
}
.col-md-6 {
position: relative;
min-height: 1px;
padding-right: 15px;
padding-left: 15px;
display: table-cell;
text-align: center;
vertical-align: middle;
}
Give style "text-align:center" to the "col-md-6" div. And display: inline-block to #goodbutton and #badbutton.
Just for example
#badbutton, #goodbutton {
height: 50px;
width: 50px;
display: inline-block;
background: #444;
vertical-align: middle;
}
Sample fiddle here
http://jsfiddle.net/Lw27ofb1/

Categories