如题,代码如下:

```{css}
.ring {
    align-items: center;
    justify-content: center;
    margin: auto;
    width: 1.875rem;
    height: 1.875rem;
    border: 0.5px solid #317ef3;
    border-radius: 50%;
    box-sizing: border-box;
}

.className1 {
  font-size: 18px;
  color: red;
  font-weight: bold;
  text-align: center;
  border-right: 1px solid #555;
  background-color: lightgrey;
}

.className2 {
  min-width: 100px;
  text-align: center;
}
```

```{r}
library(DT)

set.seed(2022)
data <- data.frame(
  type1 = sort(rep(LETTERS[1:20], 2)), 
  type2 = rep(c('NO', 'YES'), 20),
  value1 = sample(200:2000, 40),
  value2 = sample(200:2000, 40),
  level = sample(1:5, 40, replace = TRUE)
)

datatable(data, options = list(
  pageLength = 5,
  columnDefs = list(
    list(targets = 1, class = 'ring'),
    list(targets = 2, class = 'className1'),
    list(targets = c(3, 4), class = 'className2'),
    list(targets = 5, class = 'dt-center')
  )
))
```

效果如下:

    yuanfan 这是一个 CSS 优先级问题。简单说来就是一句话:如果一个元素身上有多条样式规则定义了同样的样式属性,那么更细致的规则会胜出。估计这一点 CSS 基础知识你已经知道了,而这里的问题就是为啥你的文本居中规则输了,或者确切地说,你的规则输给了谁?答案是这样:默认情况下,DT 会右对齐数值类型的列。具体办法是给数值列赋一个 dt-right 的类,其 CSS 规则定义为:

    table.dataTable th.dt-right, table.dataTable td.dt-right {
      text-align: right;
    }

    这便是你的仇家——你的规则不如它细致:

    .className2 {
      text-align: center;
    }

    它是定义给带有 dataTable 类的 <table> 元素中的 th(表头)和 td(单元格)的,而你是定义给任意带有 className2 元素的。于是细致选择打赢了任意选择。为了翻盘,你必须要和它一样细致或更细致,锁定你要选择的对象:

    table.dataTable th.className2, table.dataTable td.className2 {
      min-width: 100px;
      text-align: center;
    }

    在这里一样细致就够了,因为最终生成的 HTML 元素形如 <td class="dt-right className2">className2 出现的位置更靠后,后来者居上,优先级更高,所以它会赢了 dt.right,战斗出来的结果就是文本会居中对齐。

    注意这里只有多条 CSS 规则定义同一样式属性时才会引发战斗,比如大家都试图定义 text-align 属性。如果不同细致程度的规则定义不同的属性,那么就不会发生冲突。前两个 .ring.className1 类都达成了它们的目的,就是因为没有其它规则来定义这些蓝框框和灰板板,否则你可能也需要啰嗦定义 table.dataTable th.ring 等等。

    又及:这种问题不需要看整篇 HTML 源代码;浏览器中打开这个网页,在有问题的元素上点右键,点 Inspect 菜单(有些浏览器可能叫 Inspect Element,我不知道中文界面中是怎么翻译的),就可以查看那个元素的源码以及附属的所有 CSS 样式。你会看到 .className2 的样式有一条删除线,这就表示它被别的规则覆盖了,然后也可以看见 dt-right 的定义。

      谢谢,我看懂了。我用谷歌浏览器打开了那个 html 文件,然后按 F12 ,再选中我想查看的元素能够看到:

      <th class="dt-right className2 sorting" tabindex="0" aria-controls="DataTables_Table_14" rowspan="1" colspan="1" aria-label="value1: activate to sort column ascending">value1</th>

      看来我碰到过好几次设定样式不起作用,都可能是因为自定义样式被默认样式覆盖了。

      yihui
      本楼主搭自己的车问一个别的问题,应该可以不算作不遵守论坛规定吧。

      我知道在 DT 包中比如dt-head-center表示表头的文字居中,dt-body-center表示表格主体的文字居中。当我想要让自定义的类名也可以有head|body这个选项的话应该怎么弄?

      当然啦,我现在知道你已经提过可以分别对th(表头)和 td(单元格)自定义样式,可是我想不到可以怎么把head|body选项加上去。难不成其实 DataTable 并不是只写了一个样式dt-center再赋予了这个样式head|body选项,而是本来就是分别写好了dt-head-centerdt-body-center两个样式么?

        yuanfan 本楼主搭自己的车

        搭。

        yuanfan 难不成其实 DataTable 并不是只写了一个样式 dt-center 再赋予了这个样式 head|body 选项,而是本来就是分别写好了 dt-head-centerdt-body-center 两个样式么?

        难不成也难成了。是的,它就是这么干的,写了两个类名:https://github.com/DataTables/DataTablesSrc/blob/fe28d4/css/typography.scss#L47-L50

        yuanfan 当我想要让自定义的类名也可以有 head|body 这个选项的话应该怎么弄?

        键盘在手,天下我有。你的类名你做主,随你用什么名都行。要是觊觎 DataTables 自己的类名,你都可以用它们,然后用你的规则覆盖它的规则。(不过我不太确定我是否读懂了这个问题)

          yihui

          不过我不太确定我是否读懂了这个问题

          你给的链接就是我一直想找的,你写的答案也解答了我的问题。

          原本是我脑洞太大了,以为随便写好一个类名比如dt-center以后,不知道做了什么隐藏设定后,在类名里加上head|body选项就能分别对表头和单元格起作用。

          现在知道这过程是如此朴实无华。

          3 个月 后