Can it be done with CSS? Grouping categories on category page

What I’d like to do (as I know there’s no baked in setting or feature set) is use CSS to group categories on the home page.

I’m not looking to nest categories, but just group some together and possibly put a header on them. I know the individual categories can be “separated” with padding, and I know each category can be targeted by category ID or category name. So what I’m hoping is to be able to replicate something that looks like this:

image

I realize for simplicity, the categories would have to be in their sorted order, and each category targeted by catediry_id, but I’m thinking that there’s possibly some CSS that can throw padding after one category or before another.

The big question is there the ability to insert some text in the padding to create a header?

The propose of this is to first break up the long category list view, but separate: example

  • category 1-2 under “staff” header

  • Category 3-4 under “community resources)

  • categories 5,8,11,12,13 “under general discussion categories”

I don’t want to make these sub categories, I like the structure and category system just as it is. All I want to do is display the categories a little differently on the categories view page. Ideally this is just a visual layout, NOTHING to change with the library structure of the platform.

Any idea how to make this happen?

This would be kind of a game changer for my work collaboration site’s layout.

Sam, codinghorror, do you think there would be a way to create a grouping step in the category reorganization menu that could do this natively, say as an option (grouping on/off).just put the categories in order within main page grouping and it could automatically separare them. In core, plugin or a theme component?

3 „Gefällt mir“

anyone? buehler.

feedback appreciated

This kind of stuff is possible in a theme component but extremely complicated. I think you would need to override templates which makes this also pretty fragile.

4 „Gefällt mir“

A bit late :smile: but maybe someone else needs it. I must mention that:

  • Not all the CSS code is required, especially the borders and the background colors for table rows, so feel free to adjust them as you like.
  • I had to change the layout from the regular table into flex cause you can’t have negative margins on table rows and other layout issues, and well…is more flexible :smile:
  • Replace Category Group 1 and Category Group 2 with your desired category group names
  • In my example I’ve used the category ID’s 2 and 4, so using chrome dev tools to inspect ( see pic below), find the right category id and replace [data-category-id="2"] and [data-category-id="4"] in my example with your id(s).

Paste this inside the Common tab:

.category-list{
    display: flex;
    flex-direction: column;
}
.category-list thead tr{
    display: flex;
}
.category-list .topics {
    width: 95px;
    margin-left: auto;
    min-width: 95px;
    white-space: nowrap;
}
.category-list tbody tr {
    background-color: var(--primary-very-low);
    box-sizing: border-box;
    display: flex;
}
body .category-list [data-category-id="2"],body .category-list [data-category-id="4"] {
    position: relative;
    margin-top: 50px;
}
body [data-category-id="2"]::before {
    content: "Category Group 1";
}
body [data-category-id="4"]::before {
    content: "Category Group 2";
}
body [data-category-id="2"]::before,body [data-category-id="4"]::before {
    position: absolute;
    top: -35px;
    left: 0;
    font-weight: bold;
    font-size: 15px;
    text-transform: uppercase;
    color: var(--primary-medium);
}

Paste this inside the Desktop tab:

.category-list tbody tr {
    margin-bottom: 15px;
    border: 1px solid var(--primary-low);
}

And this inside the Mobile tab:

body .category-list-item.category .posts {
    width: auto;
    margin-left: auto;
}
body .category-list-item>footer,body .subcategory-list-item>footer{
    background-color: var(--primary-very-low);
}
.categories-list .category-list th {
    padding: 0;
}
.category-list-item>footer .category-stat, .subcategory-list-item>footer .category-stat {
    float: right;
}
.category-list-item>footer .category-stat:first-child, .subcategory-list-item>footer .category-stat:first-child{
    margin-right: 0;
}
body .category-list-item.category tr:first-of-type{
    padding: 10px 0;
    border-bottom: 1px solid var(--primary-low);
}
body tr.category-topic-link:last-of-type{
    border-bottom: 1px solid var(--primary-low);
}
body .categories-list .category-list th {
    padding: 0;
}
body .category-list-item {
    border-top: none;
    margin-bottom: 10px;
}
body .category-list-item {
    padding: 0;
    border: 1px solid var(--primary-low)!important;
}
.category-list-item>footer, .subcategory-list-item>footer {
    border-top: none;
}

And this is how it looks on desktop and mobile resolutions:

10 „Gefällt mir“

Hi Cos
]very interesting; thank you for sharing. in the same spirit (that of obtaining a better presentation, we are trying to put, in front of discourse, a wordpress page with a specific presentation and we would like to "send on this page, category names, for example those which have received a response , those chosen by the user, or then a determinate category; do you think this is possible and if so how?

1 „Gefällt mir“

I’m afraid you can’t do that just by CSS. Maybe the WordPress Discourse plugin is what you need. In addition to this, the wp discourse shortcodes is also a must.
We are already using it on our WordPress website and it works great so far. This is how the plugin looks in the sidebar widget:

2 „Gefällt mir“

@sam, @cosdesign’s response works. is there any way to bake this into core’s menus so users can leave it off by default, but then set the headers in the admin panel for group header titles, and in each category’s attributes page, select from a dropdown of the enabled section headers from the admin panel so the category just falls under the header.

This shouldn’t be terribly difficult to add to the platform and would really improve large multi user role and group, multi category installations

1 „Gefällt mir“

Diese Art von Gruppierung wird jetzt im Discourse-Kern unterstützt:

Wählen Sie „Unterkategorien mit hervorgehobenen Themen“ als „Desktop-Kategorie-Seitenstil“:

Und dann wird Ihre Kategorieseite ungefähr so aussehen:

5 „Gefällt mir“

Ist es mit RTL möglich? Ich habe es versucht, aber ich bin gescheitert :broken_heart:

Das ergibt Sinn. Die Kern-Discourse-Stylesheets werden hier gespiegelt, um eine RTL-Version zu erstellen: discourse/lib/stylesheet/compiler.rb at main · discourse/discourse · GitHub. Ich glaube nicht, dass CSS-Dateien, die von Themes hinzugefügt werden, kompiliert werden, um eine RTL-Version zu erstellen. Wenn das stimmt, würde das die Probleme erklären, auf die Sie bei Themes gestoßen sind, wenn ein RTL-Layout verwendet wird.

Sie könnten dies bestätigen, indem Sie einige CSS-Regeln mit einer Richtung zu Ihrem Website-Theme hinzufügen, dann die Website mit einem RTL-Locale besuchen und sehen, ob die Richtung gespiegelt wurde. Ich glaube nicht, dass sie gespiegelt wird.

Wenn Sie beispielsweise dies zu Ihrem Theme hinzufügen:

.category-list-item footer .category-stat, .subcategory-list-item footer .category-stat {
    float: right;
}

Ich glaube nicht, dass es in Folgendes umgewandelt wird:

.category-list-item footer .category-stat, .subcategory-list-item footer .category-stat {
    float: left;
}

Ich stimme Ihnen zu, ich bin immer noch verwirrt, den obigen Code zu verwenden :confused:

Irgendwelche Vorschläge?

Kennen Sie ein Beispiel für ein Theme, das nicht mit RTL funktioniert? Wenn ja, posten Sie hier einen Link zum Theme und ich werde meine Theorie testen und erklären, was schief läuft, nachdem ich es getestet habe.

Bearbeiten: Hier ist eine Erklärung des Problems:

Für die CSS-Dateien im Haupt-Discourse-Codebase wird das RTL-CSS erstellt, indem die meisten CSS-Regeln, die von der Ausrichtung des Layouts der Website abhängen, “gespiegelt” werden. Zum Beispiel wird padding-left zu padding-right gespiegelt. Dies geschieht mit dem RTLcss-Gem: GitHub - discourse/rtlcss: A wrapper around the rtlcss npm package to flip CSS direction in Ruby.

Das Problem ist, dass Discourse-Themes ihre CSS-Regeln nicht spiegeln. Das bedeutet, dass, wenn ein Theme CSS-Regeln hat, die eine Richtung angeben, die Richtung dieselbe ist, wenn eine RTL-Sprache verwendet wird, wie wenn eine LTR-Sprache verwendet wird. Hier ist ein kleines Beispiel dafür:

Wenn das Theme mit einer RTL-Oberfläche verwendet wird, wird padding-left: 8px; nicht zu padding-right: 8px; gespiegelt. Dies verursacht ein kleines Problem mit der Ausrichtung. Ich bin sicher, dass es Beispiele für größere Probleme gibt, wenn Themes mit einer RTL-Sprache verwendet werden.

Dasselbe gilt für jedes CSS, das Sie im Theme-Editor zu einem Standard-Discourse-Theme hinzufügen. Hier ist ein Beispiel, das den Code aus diesem Thema verwendet: Can it be done with CSS? Grouping categories on category page - #4 by cosdesign.

Hier ist eine Regel aus diesem CSS, die eine Richtung festlegt:

body [data-category-id="2"]::before,body [data-category-id="4"]::before {
    position: absolute;
    top: -35px;
    left: 0; // this needs to be changed
    font-weight: bold;
    font-size: 15px;
    text-transform: uppercase;
    color: var(--primary-medium);
}

Mit einem RTL-Locale ist dies das Problem:

Wenn diese Regel in einer Kern-Discourse-CSS-Datei wäre, würde left: 0; automatisch in right: 0; konvertiert werden, wenn eine RTL-Sprache ausgewählt wird. Da das CSS zu einem Theme hinzugefügt wird, müssen Sie es manuell wie folgt bearbeiten:

body [data-category-id="2"]::before,body [data-category-id="4"]::before {
    position: absolute;
    top: -35px;
    right: 0; // changed to the proper position for RTL layouts
    font-weight: bold;
    font-size: 15px;
    text-transform: uppercase;
    color: var(--primary-medium);
}

Discourse fügt dem html-Tag eine rtl-Klasse hinzu, wenn ein RTL-Layout verwendet wird. Theme-Entwickler könnten diese Klasse verwenden, um ihre Themes sowohl für LTR- als auch für RTL-Layouts funktionsfähig zu machen. Dies funktioniert, und ich denke, es ist richtig, aber möglicherweise muss die Deklaration left: auto nicht vorhanden sein.

body [data-category-id="2"]::before,body [data-category-id="4"]::before {
    position: absolute;
    top: -35px;
    left: 0;
    font-weight: bold;
    font-size: 15px;
    text-transform: uppercase;
    color: var(--primary-medium);
}
/* Fix positioning for rtl layouts */
.rtl body [data-category-id="2"]::before,.rtl body [data-category-id="4"]::before {
    right: 0;
    left: auto;
}

Ich bin mir nicht sicher, ob Entwickler diesen Ansatz mit ihren Themes verfolgen sollten. Es ist zeitaufwendig und könnte zu Fehlern und Wartungsproblemen führen. Vielleicht könnte Discourse einige Themes kompilieren, die eine RTL-Version anbieten könnten. Es könnte sich lohnen, diesen Ansatz mit einigen davon zu testen:

require "rtlcss"

Rtlcss.flip_css("theme_css")

Das sollte eine kurze Antwort sein :slight_smile: Wenn das, was ich geschrieben habe, korrekt ist und in einem anderen Thema noch nicht behandelt wurde, sollte es vielleicht in ein neues Thema verschoben werden.

Diese Theme component tun vielleicht, was Sie wollen. Oder sie sind eine gute Grundlage, um sich den Code anzusehen und Ideen zu sammeln.

“Modern Category + Group boxes”, wie sie im Air Theme verwendet werden, funktionieren gut.