1

Is it possible to draw the following using html and css?

enter image description here enter image description here

I am interested only in lines part. Here is what I tried so far.

html:

<div class="outer">
  <div class="inner">
    <div class="topPart">
      TOP
    </div>
    <div class="middlePart">
      <div class="program selectedProgram">
        <div class="programName">
          foo program
        </div>

        <div class="modulesDiv">
          <div class="module">
           <div class="moduleName">
             foo module foo module foo module foo module foo module
           </div>
          </div>
          <div class="module">
           <div class="moduleName">
             foo short name
           </div>
          </div>
          <div class="module">
           <div class="moduleName">
             foo module foo module foo module foo module foo module
           </div>
          </div>
        </div>
      </div>
    </div>
    <div class="bottomPart">
      BOTTOM
    </div>
  </div>
</div>

css:

.outer {
  background-color: red;
  position: relative;
  margin: 0 auto;
  top: 40px;
  width: 200px;
  height: 2000px;
  background-image: url('https://mdn.mozillademos.org/files/7693/catfront.png');
  background-repeat: no-repeat;
  background-size: cover;
}

.inner {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  background-color: cyan;
  width: 200px;
  height: 400px/* 100vh */
  ;
}

.topPart {
  position: absolute;
  height: 10%;
  width: 100%;
  top: 0;
  background-color: pink;
  text-align: center;
}

.middlePart {
  position: absolute;
  height: 80%;
  width: 100%;
  top: 10%;
  background-color: yellow;
  text-align: center;
}

.bottomPart {
  position: absolute;
  height: 10%;
  width: 100%;
  top: 90%;
  background-color: #66aa11;
  text-align: center;
}

.program {
  height: auto;
  text-align: left;
  width: 100%;
  cursor: pointer;
  padding-top: 5%;
  padding-bottom: 5%;
  padding-left: 5%;
  padding-right: 5%;
  word-wrap: break-word;
  border-bottom: 1px solid #afadad;
  position: relative;
}

.program.selectedProgram {
  border-left: 4px solid #289efd;
}

.program .programName {
  display: inline;
  font-size: 110%;
  color: #484646;
  padding-left: 5%;
  vertical-align: middle;
}

.selectedProgram.program .programName {
  font-weight: bold;
  color: #289efd;
}

.program:hover .programName {
  color: #289efd;
}

.program .programName {
  white-space: pre-wrap;
  white-space: -moz-pre-wrap !important;
  white-space: -webkit-pre-wrap;
  white-space: -pre-wrap;
  white-space: -o-pre-wrap;
  white-space: pre-wrap;
  word-wrap: break-word;
  word-break: break-all;
  white-space: normal;
}

.modulesDiv {
  height: auto;
  width: 100%;
  position: relative;
  padding-left: 5%;
  padding-top: 5%;
  display: none;
}

.selectedProgram .modulesDiv {
  display: block;
}

.module {
  height: auto;
  text-align: left;
  width: 100%;
  cursor: pointer;
  padding-top: 5%;
  padding-bottom: 5%;
  padding-left: 5%;
  padding-right: 5%;
  word-wrap: break-word;
  position: relative;
}

.program .moduleName {
  display: inline;
  font-size: 110%;
  color: #484646;
  padding-left: 5%;
  vertical-align: middle;
}

.selectedModule.module .moduleName {
  font-weight: bold;
  color: #289efd;
}

.module:hover .moduleName {
  color: #289efd;
}

There are two problems I am facing here.

  1. I do not know how to draw a randomly positioned line using only html and css.
  2. I can not guess beforehand how much height will each module take and hence can not infer in code when I will have to draw a horizontal prong to the module name.

I refer the main name, which is in bold in screenshot as a program name and names which are indented from left as module names.

I hope someone will be able to help at least with something here.

1 Answer 1

1

I am not going to implement the details but you could use a well organised structure combined with background size to create the effect you are looking for. I am using a single-pixel SVG background image that you can stretch with background-size to generate the look you want. It also does not sacrifice the actual semantics:

ul {
  padding: 0;
  margin: 0;
  list-style: none;
  padding-left: 5px;
  background: url( "data:image/svg+xml;charset=utf8,<svg width='100%' height='100%' viewBox='0 0 1 1' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' xml:space='preserve' preserveAspectRatio='none'><rect x='0' y='0' width='1' height='1' fill='gray' stroke='none' /></svg>" );
  background-size: 1px calc(100% - .5em);
  background-position: top 0 left 5px;
  background-repeat: no-repeat;
}

li {
  padding: 0;
  padding-left: 10px;
  background: url( "data:image/svg+xml;charset=utf8,<svg width='100%' height='100%' viewBox='0 0 1 1' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' xml:space='preserve' preserveAspectRatio='none'><rect x='0' y='0' width='1' height='1' fill='gray' stroke='none' /></svg>" );
  background-size: 8px 1px;
  background-position: top .5em left 0;
  background-repeat: no-repeat;
}
<h1>List</h1>
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Lipsum Dolor</li>
  <li>
    Sit Amet:
    <ul>
      <li>Dolor</li>
      <li>Lorem</li>
      <li>Ipsum</li>
      <li>Datia</li>
    </ul>
  </li>
  <li>Other</li>
</ul>

Going a little further to make the last item not stretch like crazy we will have to use multiply background definitions, so this cannot be made compatible with some older browsers, but it works regardless:

ul, h1 {
  padding: 0;
  margin: 0;
  list-style: none;
}

h1 {
  font-size: 1rem;
  color: gray;
  border-bottom: 1px solid gray;
}


li {
  padding: 0;
  padding-left: 13px;
  background: url( "data:image/svg+xml;charset=utf8,<svg width='100%' height='100%' viewBox='0 0 1 1' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' xml:space='preserve' preserveAspectRatio='none'><rect x='0' y='0' width='1' height='1' fill='gray' stroke='none' /></svg>" ), url( "data:image/svg+xml;charset=utf8,<svg width='100%' height='100%' viewBox='0 0 1 1' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' xml:space='preserve' preserveAspectRatio='none'><rect x='0' y='0' width='1' height='1' fill='gray' stroke='none' /></svg>" );
  background-size: 8px 1px, 1px 100%;
  background-position: top .5em left 5px, top 0 left 5px;
  background-repeat: no-repeat, no-repeat;
}

li:last-of-type {
  background-size: 8px 1px, 1px .5em;
}
<h1>List</h1>
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Lipsum Dolor</li>
  <li>
    Sit Amet:
    <ul>
      <li>Dolor</li>
      <li>Lorem</li>
      <li>Ipsum</li>
      <li>Datia</li>
    </ul>
  </li>
</ul>

<h1>'Nother List</h1>
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Lipsum Dolor</li>
  <li>
    Sit Amet:
    <ul>
      <li>Dolor</li>
      <li>Lorem</li>
      <li>Ipsum</li>
      <li>Datia</li>
    </ul>
  </li>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Lipsum Dolor<br />Sit Amet Nanaba</li>
</ul>

Sign up to request clarification or add additional context in comments.

7 Comments

How could you solve the problem if the last li takes more than one line? For example, here.
@iloveseven Yes but things get slightly more complicated. In that case all your padding needs to go to the <li>, and you need two background images. Let me try to make you a little example.
@iloveseven I have added a little snippet with a slightly different approach - I think this one is even better but it requires support for multiply backgrounds (which most browsers have at this point!). Then you can focus on the last child (or of-type) and end the list there. You can solve a lot of these edge cases in this fashion.
The lines you draw are drawn using svg`s rect. I tried to tweak the viewBox and width and height attributes, adding the stroke-width and stroke="black" attributes, but it did not change the width of lines. Is it possible to change width of lines somehow?
Oh. That background-size trick is amazing. Thank you a lot. lol
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.