peregraum
peregraum

Reputation: 537

Dashed-styled list linking divs

I don't know exactly how to name this or how to explain it, so I'll give you some examples of what I have and what I want to create...

I have a list of divs, all of them with an own style, in a way that they look as Forums and sub-forums... Here I'll show a picture of what I have:

What I have

The code is simple:

<div id="Forums">
    <div class="category">Category</div>
    <div class="forum">Forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="forum">Forum</div>
</div>

And the css is also very easy:

.category {
    width: 95%;
    height: 3em;
    background-color: rgba(46, 183, 255, 0.67);
    margin: 2em;
    margin-bottom: 0;
}
.forum {
    width: auto;
    height: 3em;
    background-color: rgba(30, 101, 141, 0.67);
    border: dotted;
    margin-left: 4em;
}

.sub-forum {
    width: auto;
    height: 3em;
    background-color: rgba(12, 50, 69, 0.67);
    border: dotted;
    margin-left: 7em;
}

I was thinking of making a design so the categories, the forums and sub-forums are linked with a dashed-styled "list"... I don't know how to describe it, so I've made a blueprint:

What I want

Is it possible to acquire this? How can I do it?

Thanks!

Upvotes: 12

Views: 560

Answers (4)

web-tiki
web-tiki

Reputation: 103810

Dynamic CSS only solution

First, this involves markup modifications for two reasons :

1. HTML Semantics

Your content is organized in herachy, category > forum > sub forum (like a menu) so to follow HTML semanitcs you need to use nested lists ul > li > ul > li ...

2. Styling

Changing the markup to nested elements will alow you to target last and first elements of each level with the :last-child and :first-child pseudo selectors and style them accordingly.

DEMO

HTML :

<ul id="Forums">
    <li class="category"><div>Category</div>
        <ul>
            <li class="forum"><div>Forum</div>
                <ul>
                    <li class="sub-forum">Sub-forum</li>
                    <li class="sub-forum">Sub-forum</li>
                    <li class="sub-forum">Sub-forum</li>
                </ul>
            </li>
            <li class="forum"><div>Forum</div></li>
        </ul>
    </li>
    <li class="category"><div>Category</div>
    </li>
    <li class="category"><div>Category</div>
        <ul>
            <li class="forum"><div>Forum</div>
                <ul>
                    <li class="sub-forum">Sub-forum</li>
                    <li class="sub-forum">Sub-forum</li>
                </ul>
            </li>
            <li class="forum"><div>Forum</div>
                <ul>
                    <li class="sub-forum">Sub-forum</li>
                    <li class="sub-forum">Sub-forum</li>
                </ul>
            </li>
             <li class="forum"><div>Forum</div>
                <ul>
                    <li class="sub-forum">Sub-forum</li>
                    <li class="sub-forum">Sub-forum</li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

CSS :

ul, li{
    list-style-type:none;
    margin:0; padding:0;
    position:relative;
}
.category > div{
    width: 95%; height: 3em;
    background-color: rgba(46, 183, 255, 0.67);
}
.forum {
    margin-left: 2em;
}
.forum > div, .sub-forum{
    height: 3em;
    border: dotted;
}
.forum > div{    
    background-color: rgba(30, 101, 141, 0.67);
}
.sub-forum {
    margin-left: 3em;
    background-color: rgba(12, 50, 69, 0.67);
}
.category li:before, .forum:after{
    content:'';
    position:absolute;
    right:100%;
    border-bottom: 0.2em dotted;
}
.category .forum:before{
    top:-1.5em; 
    height:100%; width:1em;
    border-left: 0.2em dotted;
    border-bottom-color: transparent;
}
.forum:last-child:before{
    height:3em;    
}
.forum:first-child:before{
    top:0;
    bottom:1.5em;    
}
.forum:after{
    top:1.5em;
    width:1.2em;
}
.sub-forum:before{
    bottom:50%;
    width:3.5em; height: 100%;
    border-left: 0.2em dotted;
}

Upvotes: 11

Ryan Wheale
Ryan Wheale

Reputation: 28430

Here is a solution which uses pure CSS and does not rely on fixed heights or anything like that. I also want to say that if you could alter your markup to represent a nested structure, this would be a whole lot easier... just sayin':

http://jsfiddle.net/ryanwheale/EaN3G/4/

.forum,
.sub-forum {
    position: relative;
}

.forum:before,
.forum:after,
.sub-forum:before,
.sub-forum:after {
    content: " ";
    position: absolute;
    left: -1.5em;
    top: -55%;
    bottom: 50%;
    z-index: -1;
}

.forum:before,
.sub-forum:before {
    border-left: 3px dotted #000;
}
.sub-forum:before {
    left: -4.5em;
    width: 3em;
    border-right: 3px dotted #000;
    box-sizing: border-box;
}

.forum:after,
.sub-forum:after {
    width: 1.5em;
    border-bottom: 3px dotted #f00;
}

Upvotes: 1

nicael
nicael

Reputation: 19005

This is a javascript solution for dynamic list.

What I changed in original list:

  • removed alpha from list items ("categories", "forums" and "sub-forums")

  • changed text color of "forums" and "sub-forums" to white for readability

Notes

  • forums are expected to be placed in categories

  • sub-forums are expected to be placed in forums

Nothing is drawn if you violate above rules

  • categories and forums can contain no childs, it is not a problem (as you can see in my example list)


HTML (try to edit it in fiddle or somewhere else to add or remove new items!)

<div id="Forums">
    <div class="category">Category</div>
    <div class="forum">Forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="forum">Forum</div>
    <div class="forum">Forum</div>
    <div class="forum">Forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="forum">Forum</div>
    <div class="category">Category</div>
    <div class="forum">Forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="sub-forum">Sub-forum</div>
    <div class="forum">Forum</div>
    <div class="category">Category</div>
    <div class="forum">Forum</div>
</div>

CSS (don't change default items margins by the way):

.category {
    width: 95%;
    height: 3em;
    background-color: rgba(46, 183, 255, 1);
    margin: 2em;
    margin-bottom: 0;
}
.forum {
    width: auto;
    height: 3em;
    background-color: rgba(30, 101, 141, 1);
    color:white;
    border: dotted;
    margin-left: 4em;
}

.sub-forum {
    width: auto;
    height: 3em;
    color:#ffffff;
    background-color: rgba(12, 50, 69, 1);
    border: dotted;
    margin-left: 7em;
}

Javascript

var borderWidth = "4px";
var borderColor = "black";

for (var forum = 0; forum < document.getElementsByClassName("forum").length; forum++) {
    var rect = document.createElement("div");
    rect.style.margin = "2.5em";
    rect.style.border = "dotted";
    rect.style.borderWidth = borderWidth;
    rect.style.borderColor = borderColor;
    rect.style.position = "absolute";

    if (document.getElementsByClassName("forum")[forum].previousElementSibling.className == "category") {
        rect.style.top = document.getElementsByClassName("forum")[forum].previousElementSibling.offsetTop - 10 + "px";
        rect.style.height = document.getElementsByClassName("forum")[forum].offsetTop - document.getElementsByClassName("forum")[forum].previousElementSibling.offsetTop - 2 + "px";
    } else {
        rect.style.top = document.getElementsByClassName("forum")[forum - 1].offsetTop - 10 + "px";
        rect.style.height = document.getElementsByClassName("forum")[forum].offsetTop - document.getElementsByClassName("forum")[forum - 1].offsetTop - 2 + "px";
    }

    rect.style.width = "100px";
    rect.style.zIndex = "-1";
    document.body.appendChild(rect);
}

for (var subforum = 0; subforum < document.getElementsByClassName("sub-forum").length; subforum++) {

    var rect = document.createElement("div");
    rect.style.margin = "2.5em";
    rect.style.marginLeft = "5em"
    rect.style.border = "dotted";
    rect.style.borderWidth = borderWidth;
    rect.style.borderColor = borderColor;
    rect.style.position = "absolute";

    rect.style.top = document.getElementsByClassName("sub-forum")[subforum].previousElementSibling.offsetTop - 10 + "px";
    rect.style.height = document.getElementsByClassName("sub-forum")[subforum].offsetTop - document.getElementsByClassName("sub-forum")[subforum].previousElementSibling.offsetTop - 2 + "px";

    rect.style.width = "100px";
    rect.style.zIndex = "-1";
    document.body.appendChild(rect);
    document.getElementsByClassName("sub-forum")[subforum].nextElementSibling.className;
}

JSFiddle

If anyone wanna test it, there is it and fullscreen version.

If something is bad with width, change the border width

var borderWidth="4px";

or color

var borderColor="black";

Upvotes: 2

Banana
Banana

Reputation: 7473

If the to-be style list is dynamic, you will have to involve JavaScript for the simple reason that css is not a programming language, it is a styling markup and is not suitable/designed to handle dynamic html elements.

In any case, the requested styling can be achieved using the css3 pseudo elements :after and :before

what those selectors do, is pretty simple. they add another dynamic <span> before/after the selected element. for example:

.myElement:after{

}

will add a dynamic element right after the content of .myElement

the styling of the :before/:after elements is the same as any other element, with the exclusion of the content attribute that decides what to put inside the newly created element, in most cases you would want to put nothing ('') aka blank content;

in your example list, it can be styled by inserting a :before span with a styled left border, behind the list items:

.category {
    width: 95%;
    height: 3em;
    background-color: rgba(46, 183, 255, 0.67);
    margin: 2em;
    margin-bottom: 0;
}
.forum {
    width: auto;
    height: 3em;
    background-color: rgba(30, 101, 141, 0.67);
    border: dotted;
    margin-left: 4em;
}

.sub-forum {
    width: auto;
    height: 3em;
    background-color: rgba(12, 50, 69, 0.67);
    border: dotted;
    margin-left: 7em;
}
.sub-forum:before{
    position:absolute;
    content:'';
    display:block;
    width:3.6em;
    border:4px dotted black; 
    height:3em;
    margin-left:-4em;
    margin-top:-1.5em;
    border-top:none;
    border-right:none;
    z-index:-2;
}

.forum:before{
    position:absolute;
    content:'';
    display:block;
    width:1em;
    border:4px dotted black; 
    height:15em;
    margin-left:-1.6em;
    margin-top:-13.5em;
    border-top:none;
    border-right:none;
    z-index:-2;
}
.forum:nth-of-type(2):before{
    height:1.5em;
    margin-top:0em;
}

Live example: Demo

note that the position of the new elements has to be absolute, or they will push everything down.

in case of a dynamic list, you will have to utilize JavaScript to create dynamic elements using the above styling per list item.

Upvotes: 2

Related Questions