Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Styling the first item in a css column

Tags:

css

I have a list which is displayed over multiple columns. Each of the list items is block element (display:block) and has some styling attached to it (a 1px border at the bottom). It currently looks like this:

List item    List item    List item
---------    ---------    ---------
List item    List item    List item
---------    ---------    ---------
List item    List item
---------    ---------

I would like to add an identical border to the top of the first item in each column e.g.

---------    ---------    ---------    
List item    List item    List item
---------    ---------    ---------
List item    List item    List item
---------    ---------    ---------
List item    List item
---------    ---------

I've tried :first-line and ::first-line, neither of which seem to anything in this instance (probably because it doesn't work on block elements?)

The list may vary in length so I have no way to determine how many items will be in each column so I can't user :nth-of-type() either.

Does anybody know if this can be done (or conversely if it definitely can't?)

My HTML

<ul>
  <li><a href="">List item</a></li>
  <li><a href="">List item</a></li>
  <li><a href="">List item</a></li>
  ...
</ul>

My CSS

  ul {
    list-style: none;
    padding: 21px;
    -moz-column-count: 4;
    -webkit-column-count: 4;
    column-count: 4;
    -moz-column-gap: 21px;
    -webkit-column-gap: 21px;
    column-gap: 21px;
  }
  li {
    display: block;
    -moz-column-break-inside: avoid;
    -webkit-column-break-inside: avoid;
    -mx-column-break-inside: avoid;
    column-break-inside: avoid;
    padding: 1em 0;
    border-bottom: 1px dotted #000;
  }
like image 346
chrism Avatar asked Oct 10 '13 15:10

chrism


2 Answers

Edit after seeing the code and 1 hour later: DONE! With pure CSS!

It took me a real while since I didn't want to use javascript. Here's a demos of what's really going on behind the scenes http://jsfiddle.net/mEtF6/1/, and here's the working version: http://jsfiddle.net/mEtF6/2/. If you don't understand anything, feel free to ask about it, since it's not very well documented. I had to actually add a div wrapping the 'ul' because the overflow: hidden on ul wouldn't behave as the border-top is outside the element. This is the working code:

<div>
  <ul>
    <li><a href="">List item 1</a></li>
    <li><a href="">List item 2</a></li>
    <li><a href="">List item 3</a></li>
    <li><a href="">List item 4</a></li>
    <li><a href="">List item 5</a></li>
    <li><a href="">List item 6</a></li>
    <li><a href="">List item 7</a></li>
    <li><a href="">List item 8</a></li>
    <li><a href="">List item 9</a></li>
  </ul>
</div>

And the css:

div {
  /* This will hide the white space at the right (blue in the explanation) */
  overflow: hidden;
  }

ul {
  position: relative; /* Needed to place the :before pseudo element in the proper position */
  list-style: none;
  border-top: 1px dotted #000;
  padding: 0;
  margin: 0;
  -moz-column-count: 4;
  -webkit-column-count: 4;
  column-count: 4;
  -moz-column-gap: 20px;
  -webkit-column-gap: 20px;
  column-gap: 20px;
  }

/* This 'cuts' the top margin of ul so it's displayed in the same way as the other */
ul:before {
  content: " ";
  position: absolute;
  display: block;
  width: 100%;
  height: 1px;

  /* Put the gaps on the <ul> top margin */
  top: -1px;

  /* Background-size = 1/4 of the width + 1/4 of the space between columns */
  background-size: calc(25% + 5px) 1px;

  /* Or it will hide the border-top of the ul */
  background-color: transparent;

  /* The actual white gaps at the top */
  background-image: linear-gradient(
    90deg,
    transparent calc(100% - 20px), /* All the <li> width minus the gap is transparent */
    red 20px);  /* Those 20px are white */
  }

li {
  -moz-column-break-inside: avoid;
  -webkit-column-break-inside: avoid;
  -mx-column-break-inside: avoid;
  column-break-inside: avoid;
  padding: 0;
  border-bottom: 1px dotted #000;
  }

/* This will hide the top margin of the last columns without elements */
li:last-child:before {
  position: absolute;
  /* You want to place the top  */
  margin-left: calc(25% + 5px);
  content: " ";
  display: block;
  background-color: blue;
  width: 10px;
  height: 1px;
  top: -1px;
  width: 100%;
  }

/* Make the <a> fill the whole space of the <li> */
li a {
  display: block;
  padding: 1em 0;
  }

Note: I added proper support for the <a> tags, making the whole block clickable, and not only the text inside it. You can ofc reverse it.

Note 2: tested only with FIREFOX. You might need to add some other -webkit gradients to make it cross-browser. Sorry but I'll leave this dirty work to you (; I found an apparent bug and asked a question here in SO about it.

Again, the working demo: http://jsfiddle.net/mEtF6/2/.

like image 53
Francisco Presencia Avatar answered Sep 28 '22 03:09

Francisco Presencia


add border-top: 1px dotted #000; margin-bottom: -1px; to your li style

fiddle

like image 36
jbarnett Avatar answered Sep 28 '22 02:09

jbarnett