在css列中设置第一个项目的样式

时间:2022-11-03 07:25:02

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:

我有一个显示在多列上的列表。每个列表项都是块元素(display:block)并且附加了一些样式(底部有1px边框)。它目前看起来像这样:

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.

列表的长度可能不同,因此我无法确定每列中有多少项,因此我无法使用:nth-​​of-type()。

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

有人知道这是否可以做到(或相反,如果它肯定不能?)

My HTML

我的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

我的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;
  }

4 个解决方案

#1


4  

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

看到代码后编辑,1小时后:完成!用纯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:

我花了一段时间,因为我不想使用javascript。以下是幕后http://jsfiddle.net/mEtF6/1/的真实演示,这里是工作版:http://jsfiddle.net/mEtF6/2/。如果你什么都不懂,可以随意询问,因为它没有很好的记录。我不得不实际添加一个包裹'ul'的div,因为溢出:隐藏在ul上的行为不会因为border-top在元素之外。这是工作代码:

<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:

和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.

注2:仅使用FIREFOX进行测试。您可能需要添加一些其他-webkit渐变以使其跨浏览器。对不起,但我会把这个肮脏的工作留给你(;我发现了一个明显的错误,并在此问了一个问题。

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

再次,工作演示:http://jsfiddle.net/mEtF6/2/。

#2


3  

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

添加border-top:1px点缀#000; margin-bottom:-1px;你的风格

fiddle

小提琴

#3


2  

If it's the same ul that's spanned across multiple columns and the number of items in the columns can vary. Then I can't see a way to do this. Not with CSS only at least.

如果它是跨越多列的相同ul,则列中的项目数可能会有所不同。然后我看不到这样做的方法。至少不是CSS。

I would make the columns a fixed number of items and use a :nth* pseudo selector or split the columns into different ul tags and style the first li.

我会使列成为固定数量的项目并使用:nth *伪选择器或将列拆分为不同的ul标记并设置第一个li样式。

If you want to use jQuery or similar you could maybe target the first li, find the top position of it and iterate through the others and if the top position matches add the border.

如果你想使用jQuery或者类似的东西,你可以定位第一个li,找到它的顶部位置并迭代其他的,如果顶部位置匹配则添加边框。

Edit

This JSFiddle is one solution, but it does use jQuery though:

这个JSFiddle是一个解决方案,但它确实使用jQuery:

http://jsfiddle.net/8ZRkG/

http://jsfiddle.net/8ZRkG/

With four columns: 在css列中设置第一个项目的样式

有四列:

With three columns: 在css列中设置第一个项目的样式

有三列:

#4


1  

The way the CSS3 multi-column model works is by creating a new type of container between the content-box and the content, called the column box.

CSS3多列模型的工作方式是在内容框和内容之间创建一种新类型的容器,称为列框。

Unfortunately, the current spec explicitly states:

不幸的是,目前的规范明确指出:

It is not possible to set properties/values on column boxes. For example, the background of a certain column box cannot be set and a column box has no concept of padding, margin or borders.

无法在列框上设置属性/值。例如,无法设置某个列框的背景,并且列框没有填充,边距或边框的概念。

Hence, at the present moment, there is no selector for the column boxes or the elements within, though the same page opens to the possibility that such a thing might be included in the future (why they didn't think of including it in the present spec, is beyond me).

因此,目前,列盒或其中的元素没有选择器,尽管同一页面打开了将来可能包含这样的东西的可能性(为什么他们没想到将它包含在目前的规格,超出我的意义。

Since you state you cannot edit the server-side output, you need to use Javascript. I see one solution already proposes that, though I disagree with the approach of calculating the top position of li:first-child. Instead, I propose this:

由于您声明无法编辑服务器端输出,因此您需要使用Javascript。我看到一个解决方案已经提出,虽然我不同意计算李的最高位置的方法:第一个孩子。相反,我建议这样做:

var liNum  = $('ul.columns li').length; // This computes the number of list items
var colNum = 4;                        // This is the number of columns you want

$('ul.columns li').each(function(i) {
    if ( i % Math.ceil(liNum/colNum) === 0 ) {
        $(this).addClass('top');
    }
});

Working demo

工作演示

Sure, it's a bit longer, but doesn't rely on the computed top position (which is a visual property) or on the li being :first-child. Instead, it relies on the number of elements that are in the list, which I think is the important number.

当然,它有点长,但不依赖于计算的顶部位置(这是一个视觉属性)或者是依赖于:first-child。相反,它依赖于列表中的元素数量,我认为这是重要的数字。

Of course, this is assuming you know how many columns you have (as you said you do). If you want to not rely on that piece of information, you can just compute that CSS instead:

当然,这假设你知道你有多少列(正如你所说)。如果您不想依赖这条信息,您可以改为计算CSS:

var colNum = $('ul.columns').css('column-count')

Also, if you just want to add the border to the top, and don't want to style anything else, I would perhaps edit the css directly through the .css() method instead of adding a class. If you need to target the top element for more styles or other purposes (further JS for example), then I would add the class. But that's really a matter of preference.

此外,如果您只想将边框添加到顶部,并且不想设置任何其他内容,我可能会直接通过.css()方法编辑css而不是添加类。如果您需要将top元素作为更多样式或其他目的(例如JS),那么我会添加该类。但这确实是一个偏好问题。

#1


4  

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

看到代码后编辑,1小时后:完成!用纯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:

我花了一段时间,因为我不想使用javascript。以下是幕后http://jsfiddle.net/mEtF6/1/的真实演示,这里是工作版:http://jsfiddle.net/mEtF6/2/。如果你什么都不懂,可以随意询问,因为它没有很好的记录。我不得不实际添加一个包裹'ul'的div,因为溢出:隐藏在ul上的行为不会因为border-top在元素之外。这是工作代码:

<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:

和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.

注2:仅使用FIREFOX进行测试。您可能需要添加一些其他-webkit渐变以使其跨浏览器。对不起,但我会把这个肮脏的工作留给你(;我发现了一个明显的错误,并在此问了一个问题。

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

再次,工作演示:http://jsfiddle.net/mEtF6/2/。

#2


3  

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

添加border-top:1px点缀#000; margin-bottom:-1px;你的风格

fiddle

小提琴

#3


2  

If it's the same ul that's spanned across multiple columns and the number of items in the columns can vary. Then I can't see a way to do this. Not with CSS only at least.

如果它是跨越多列的相同ul,则列中的项目数可能会有所不同。然后我看不到这样做的方法。至少不是CSS。

I would make the columns a fixed number of items and use a :nth* pseudo selector or split the columns into different ul tags and style the first li.

我会使列成为固定数量的项目并使用:nth *伪选择器或将列拆分为不同的ul标记并设置第一个li样式。

If you want to use jQuery or similar you could maybe target the first li, find the top position of it and iterate through the others and if the top position matches add the border.

如果你想使用jQuery或者类似的东西,你可以定位第一个li,找到它的顶部位置并迭代其他的,如果顶部位置匹配则添加边框。

Edit

This JSFiddle is one solution, but it does use jQuery though:

这个JSFiddle是一个解决方案,但它确实使用jQuery:

http://jsfiddle.net/8ZRkG/

http://jsfiddle.net/8ZRkG/

With four columns: 在css列中设置第一个项目的样式

有四列:

With three columns: 在css列中设置第一个项目的样式

有三列:

#4


1  

The way the CSS3 multi-column model works is by creating a new type of container between the content-box and the content, called the column box.

CSS3多列模型的工作方式是在内容框和内容之间创建一种新类型的容器,称为列框。

Unfortunately, the current spec explicitly states:

不幸的是,目前的规范明确指出:

It is not possible to set properties/values on column boxes. For example, the background of a certain column box cannot be set and a column box has no concept of padding, margin or borders.

无法在列框上设置属性/值。例如,无法设置某个列框的背景,并且列框没有填充,边距或边框的概念。

Hence, at the present moment, there is no selector for the column boxes or the elements within, though the same page opens to the possibility that such a thing might be included in the future (why they didn't think of including it in the present spec, is beyond me).

因此,目前,列盒或其中的元素没有选择器,尽管同一页面打开了将来可能包含这样的东西的可能性(为什么他们没想到将它包含在目前的规格,超出我的意义。

Since you state you cannot edit the server-side output, you need to use Javascript. I see one solution already proposes that, though I disagree with the approach of calculating the top position of li:first-child. Instead, I propose this:

由于您声明无法编辑服务器端输出,因此您需要使用Javascript。我看到一个解决方案已经提出,虽然我不同意计算李的最高位置的方法:第一个孩子。相反,我建议这样做:

var liNum  = $('ul.columns li').length; // This computes the number of list items
var colNum = 4;                        // This is the number of columns you want

$('ul.columns li').each(function(i) {
    if ( i % Math.ceil(liNum/colNum) === 0 ) {
        $(this).addClass('top');
    }
});

Working demo

工作演示

Sure, it's a bit longer, but doesn't rely on the computed top position (which is a visual property) or on the li being :first-child. Instead, it relies on the number of elements that are in the list, which I think is the important number.

当然,它有点长,但不依赖于计算的顶部位置(这是一个视觉属性)或者是依赖于:first-child。相反,它依赖于列表中的元素数量,我认为这是重要的数字。

Of course, this is assuming you know how many columns you have (as you said you do). If you want to not rely on that piece of information, you can just compute that CSS instead:

当然,这假设你知道你有多少列(正如你所说)。如果您不想依赖这条信息,您可以改为计算CSS:

var colNum = $('ul.columns').css('column-count')

Also, if you just want to add the border to the top, and don't want to style anything else, I would perhaps edit the css directly through the .css() method instead of adding a class. If you need to target the top element for more styles or other purposes (further JS for example), then I would add the class. But that's really a matter of preference.

此外,如果您只想将边框添加到顶部,并且不想设置任何其他内容,我可能会直接通过.css()方法编辑css而不是添加类。如果您需要将top元素作为更多样式或其他目的(例如JS),那么我会添加该类。但这确实是一个偏好问题。