• Welcome to Simple Machines Community Forum. Please login or sign up.
January 16, 2022, 10:33:45 PM

News:

SMF 2.0.19 has been released! Please update. Read more.


[SMF 2.1]Remixed Breadcrumb

Started by TwitchisMental, January 03, 2022, 02:04:09 PM

Previous topic - Next topic

TwitchisMental

January 03, 2022, 02:04:09 PM Last Edit: January 03, 2022, 02:17:50 PM by TwitchisMental
Remixed Breadcrumb Tutorial

In this tutorial we are going to take the default breadcrumb and knock it up a notch. BAM! You cannot see attachments on this board.

End Result - 
You cannot see attachments on this board.
 
I am just using a copy of the default theme for this tutorial.

Step 1. We will need to do the CSS. Go to the css folder and open the index.css in your favorite text editor. (I use Notepad++)

Step 2. Go to the very bottom of the CSS file. Copy and paste this -
/*The Breadcrumb*/

/*Main class gives border, font size, and turns off list style*/

.breadcrumb {
  font: 1em sans-serif;
  list-style: none;
  border: 1px solid rgba(221,211,211,1);
}
/*Flex it up */

.breadcrumb ul {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
/*We don't want the p tag to have a margin*/
.breadcrumb p {
  margin: 0;
}

/* Fall in line li */
.breadcrumb li {
  display: inline-flex;
}

/*Forming the arrows*/
.breadcrumb li {
  background-color: rgb(85, 126, 160);
  box-sizing: border-box;
  color: rgb(226, 233, 243);
  display: inline-flex;
  max-height: 2em;
  padding: .5em 1em .5em 1.5em;
  position: relative;
  text-decoration: none;
  transition-timing-function: ease-in;
  transition: 0.5s;
  font-weight: 700;
}

.breadcrumb li:before {
  border-top: 1em solid transparent;
  border-bottom: 1em solid transparent;
  border-left: 1em solid #fff;
  content: "";
  position: absolute;
  top: 0;
  right: -1.25em;
  z-index: 1;
}

.breadcrumb li:after {
  border-top: 1em solid transparent;
  border-bottom: 1em solid transparent;
  border-left: 1em solid rgb(85, 126, 160);
  content: "";
  position: absolute;
  top: 0;
  right: -0.9em;
  transition-timing-function: ease-in;
  transition: 0.5s;
  z-index: 1;
}

/* Colors */

.breadcrumb strong {
    color: rgb(85, 126, 160);
}

.breadcrumb li a {
    color: rgb(226, 233, 243);
}

.breadcrumb li a:hover {
    color: rgb(85, 126, 160);
}

.breadcrumb li:hover a {
    color: rgb(85, 126, 160);
}

.breadcrumb li:hover {
  background-color: rgb(226, 233, 243);
  color: rgb(85, 126, 160);
}

.breadcrumb li:hover:after {
  border-left-color: rgb(226, 233, 243);
  color: rgb(85, 126, 160);
}

.breadcrumb li:last-child  {
    background-color: rgb(226, 233, 243);
    color: rgb(85, 126, 160);
}

.breadcrumb li:last-child a  {
    color: rgb(85, 126, 160);
}

.breadcrumb li:last-child::after {
    border-left-color: rgb(226, 233, 243);
}

Step 3.  Save the file and refresh your browser. Wait there is no difference..... What is this blasphemy??  This is because we now need to edit the index template to actually call upon our new css. See Step 4. :D

Step 4. CSS meet HTML, HTML Meet CSS.  Go ahead and open the index.template.php file located in the base of your theme folder.  Find the following line 441 -

    // If linktree is empty, just return - also allow an override.
Step 5. We will need to modify this area so that it uses our new breadcrumb CSS. We will be removing the the "unread links" and changing some class names. This will allow the breadcrumb to show up correctly.

Find -
    // If linktree is empty, just return - also allow an override.
    if (empty($context['linktree']) || (!empty($context['dont_default_linktree']) && !$force_show))
        return;
    echo '
                <div class="navigate_section">
                    <ul>';

    if ($context['user']['is_logged'])
        echo '
                        <li class="unread_links">
                            <a href="', $scripturl, '?action=unread" title="', $txt['unread_since_visit'], '">', $txt['view_unread_category'], '</a>
                            <a href="', $scripturl, '?action=unreadreplies" title="', $txt['show_unread_replies'], '">', $txt['unread_replies'], '</a>
                        </li>';

    // Each tree item has a URL and name. Some may have extra_before and extra_after.
    foreach ($context['linktree'] as $link_num => $tree)
    {
        echo '
                        <li', ($link_num == count($context['linktree']) - 1) ? ' class="last"' : '', '>';

        // Don't show a separator for the first one.
        // Better here. Always points to the next level when the linktree breaks to a second line.
        // Picked a better looking HTML entity, and added support for RTL plus a span for styling.
        if ($link_num != 0)
            echo '
                            <span class="dividers">', $context['right_to_left'] ? ' &#9668; ' : ' &#9658; ', '</span>';

        // Show something before the link?
        if (isset($tree['extra_before']))
            echo $tree['extra_before'], ' ';

        // Show the link, including a URL if it should have one.
        if (isset($tree['url']))
            echo '
                            <a href="' . $tree['url'] . '"><span>' . $tree['name'] . '</span></a>';
        else
            echo '
                            <span>' . $tree['name'] . '</span>';

        // Show something after the link...?
        if (isset($tree['extra_after']))
            echo ' ', $tree['extra_after'];

        echo '
                        </li>';
    }

    echo '
                    </ul>
                </div><!-- .navigate_section -->';

    $shown_linktree = true;
}

Replace With  -

    // If linktree is empty, just return - also allow an override.
    if (empty($context['linktree']) || (!empty($context['dont_default_linktree']) && !$force_show))
        return;
    echo '
                <div class="breadcrumb_holder">
                    <ul class="breadcrumb">';

    // Each tree item has a URL and name. Some may have extra_before and extra_after.
    foreach ($context['linktree'] as $link_num => $tree)
    {
        echo '
                        <li', ($link_num == count($context['linktree']) - 1) ? ' class="last"' : '', '>';

        // Show something before the link?
        if (isset($tree['extra_before']))
            echo $tree['extra_before'], ' ';

        // Show the link, including a URL if it should have one.
        if (isset($tree['url']))
            echo '
                            <a href="' . $tree['url'] . '"><span>' . $tree['name'] . '</span></a>';
        else
            echo '
                            <span>' . $tree['name'] . '</span>';

        // Show something after the link...?
        if (isset($tree['extra_after']))
            echo ' ', $tree['extra_after'];

        echo '
                        </li>';
    }

    echo '
                    </ul>
                </div><!-- .navigate_section -->';

    $shown_linktree = true;
}

Step 6. Refresh the page and you should now be seeing -

You cannot see attachments on this board.

Step 7. What about the unread links? Where did they go? I WANT MY UNREAD LINKS!!!
I understand and I got you covered. We can relocate those links to the top bar. Within the same index.template.php file Find -

        // Thirdly, alerts
        echo '
                <li>
                    <a href="', $scripturl, '?action=profile;area=showalerts;u=', $context['user']['id'], '"', !empty($context['self_alerts']) ? ' class="active"' : '', ' id="alerts_menu_top">', $txt['alerts'], !empty($context['user']['alerts']) ? ' <span class="amt">' . $context['user']['alerts'] . '</span>' : '', '</a>
                    <div id="alerts_menu" class="top_menu scrollable"></div>
                </li>';
               
Replace With -

        // Thirdly, alerts
        echo '
                <li>
                    <a href="', $scripturl, '?action=profile;area=showalerts;u=', $context['user']['id'], '"', !empty($context['self_alerts']) ? ' class="active"' : '', ' id="alerts_menu_top">', $txt['alerts'], !empty($context['user']['alerts']) ? ' <span class="amt">' . $context['user']['alerts'] . '</span>' : '', '</a>
                    <div id="alerts_menu" class="top_menu scrollable"></div>
                </li>';
               
        // Fourth, the unread buttons
       
        echo '
                <li>
                    <a href="', $scripturl, '?action=unread" title="', $txt['unread_since_visit'], '">', $txt['view_unread_category'], '</a>
                </li>
                <li>
                    <a href="', $scripturl, '?action=unreadreplies" title="', $txt['show_unread_replies'], '">', $txt['unread_replies'], '</a>
                </li>';
This will bring those links to the top bar as you can see here -

You cannot see attachments on this board.

Step 8. Refresh that browser and enjoy your new breadcrumb.


Shoutout to Diego Andrés and Sesquipedalian for their help with sorting out a bug.
Original Idea Came From - https://codepen.io/thallysbezerra/embed/NAyEPB?height=316&theme-id=0&default-tab=result

Diego Andrés

Very nice, might use it in the future  :P

SMF Tricks - Free & Premium Responsive Themes for SMF.

Aleksi "Lex" Kilpinen

Have to say, this looks like a cool little trick. Might have to try it out :)
A Finnish Project Manager (Support Specialist)
 Happily running multiple SMF 2.x installations.
  Fooling around with i7-10700 @ 2,90GHz-4.80GHz / 16Gb / RTX-2070 Super / 3840x2160 / Win 10 x64


How you can help SMF

"Before you allow people access to your forum, especially in an administrative position, you must be aware that that person can seriously damage your forum. Therefore, you should only allow people that you trust, implicitly, to have such access." -Douglas

TwitchisMental

Quote from: Diego Andrés on January 03, 2022, 02:08:19 PMVery nice, might use it in the future  :P
Thank you, I hope you do :).

Quote from: Aleksi on January 03, 2022, 02:09:48 PMHave to say, this looks like a cool little trick. Might have to try it out :)
Thank you, I hope you do too :).

d3vcho

"Greeting Death as an old friend, they departed this life as equals"

Shades.


ShadesWeb.com - Custom Logos
https://shadesweb.com

BikerHound.com - Sniffing out the road ahead
https://bikerhound.com

Dream as if you'll live forever; Live as if you'll die today. - James Dean

Mick.


TwitchisMental


Wellwisher

I can see this having really good practical applications on certain themes. Nice work.

Kindred

January 04, 2022, 10:51:19 AM #9 Last Edit: January 04, 2022, 02:57:02 PM by Kindred
nicely done....   implemented in a new theme for 2.1 that I am working on for a site.


note for custom work beyond the Curve/Curve2 theme...
Change all instances of these for the colors to match your theme:
rgb(85, 126, 160) (this is the base background color, the border color and the hover font color)
rgb(226, 233, 243) (this is the base font color and the hover background color)

If you don't change ALL of them consistently, you may get some odd effects.

BTW: To see it  test2.turtleshellprod.com
Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

Arantor

Nice - I'd done something similar myself recently.

If I can suggest a couple of possible improvements:

First... CSS variables, something akin to this (have not tested)

/*The Breadcrumb*/

/*Main class gives border, font size, and turns off list style*/

.breadcrumb {
  font: 1em sans-serif;
  list-style: none;
  border: 1px solid rgba(221,211,211,1);

  --main-light-color: rgb(226, 233, 243);
  --main-dark-color: rgb(85, 126, 160);
}
/*Flex it up */

.breadcrumb ul {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
/*We don't want the p tag to have a margin*/
.breadcrumb p {
  margin: 0;
}

/* Fall in line li */
.breadcrumb li {
  display: inline-flex;
}

/*Forming the arrows*/
.breadcrumb li {
  background-color: var(--main-dark-color);
  box-sizing: border-box;
  color: var(--main-light-color);
  display: inline-flex;
  max-height: 2em;
  padding: .5em 1em .5em 1.5em;
  position: relative;
  text-decoration: none;
  transition-timing-function: ease-in;
  transition: 0.5s;
  font-weight: 700;
}

.breadcrumb li:before {
  border-top: 1em solid transparent;
  border-bottom: 1em solid transparent;
  border-left: 1em solid #fff;
  content: "";
  position: absolute;
  top: 0;
  right: -1.25em;
  z-index: 1;
}

.breadcrumb li:after {
  border-top: 1em solid transparent;
  border-bottom: 1em solid transparent;
  border-left: 1em solid var(--main-dark-color);
  content: "";
  position: absolute;
  top: 0;
  right: -0.9em;
  transition-timing-function: ease-in;
  transition: 0.5s;
  z-index: 1;
}

/* Colors */

.breadcrumb strong {
    color: var(--main-dark-color);
}

.breadcrumb li a {
    color: var(--main-light-color);
}

.breadcrumb li a:hover {
    color: var(--main-dark-color);
}

.breadcrumb li:hover a {
    color: var(--main-dark-color);
}

.breadcrumb li:hover {
  background-color: var(--main-light-color);
  color: var(--main-dark-color);
}

.breadcrumb li:hover:after {
  border-left-color: var(--main-light-color);
  color: var(--main-dark-color);
}

.breadcrumb li:last-child  {
    background-color: var(--main-light-color);
    color: var(--main-dark-color);
}

.breadcrumb li:last-child a  {
    color: var(--main-dark-color);
}

.breadcrumb li:last-child::after {
    border-left-color: var(--main-light-color);
}

This way you only have to change two colour definitions to restyle the bulk of it to fit a given theme. I'm not sure about the border around the breadcrumb in general or the white fill on the left, couldn't decide if that should be a variable or not.

The other thing is a bit (lot) more fiddly around laying it out on mobile. It will normally wrap to multiple lines which is a bit annoying.

What I did (not the same markup or styling at this but food for thought) was to have the normal breadcrumb trail on desktop... I'd share a link but the site's not open yet.

You cannot see attachments on this board.

With it collapsing by default on mobile...

You cannot see attachments on this board.

And using a widget to expand it vertically when called for...

You cannot see attachments on this board.

Stylewise, well you can see I have Font Awesome loaded but this doesn't make that much odds in the grand scheme of things.

How the toggle is done is by way of an <input type="checkbox"> where the main styling is dropped entirely (appearance: none), then :after is populated with a glyph from Font Awesome and a different glyph is used with :checked on the input box.

The rest of the styling is basically about using :checked as a selector on the input and filtering down the .arrow items thereafter based on 1) a media query and 2) whether or not the checkbox is checked.

It's not a dropin replacement code-wise since SMF doesn't yet have a built in SCSS compiler (I added one to mine), but the relevant styling in case it is of use to anyone:

@media screen and (max-width: 767px) {
.arrowbar {
input ~ .arrow {
display: none;
}

.arrow:first-of-type {
display: block;
}

input:checked ~ .arrow {
display: block;
}

input {
position: absolute;
}

input[type="checkbox"]::after {
content: "\f0c9";
font-family: "Font Awesome 5 Free";
font-weight: 900;
}

.arrow {
padding-left: 50px;
}
}
}
@media screen and (min-width: 768px) {
.arrowbar input {
display: none;
}
}

In case it helps with the relevant placement of the input vs the other elements...

{{#if context.linktree}}
<div class="navigate_section">
<div class="arrowbar">
<input type="checkbox">
{{#each context.linktree}}
<div class="arrow{{#if @last}} active{{/if}}">
{{#if url}}
<a href="{{url}}"><span>{{#if @first}}<i class="fas fa-home fa-fw"></i> {{/if}}{{{name}}}</span></a>
{{else}}
<span>{{{name}}}</span>
{{/if}}
</div>
{{/each}}
</div>
</div>
{{/if}}

Hopefully this will make sense and can be adapted to SMF.
No good deed goes unpunished
All helpful urges should be circumvented

Diego Andrés

Neat.
I used to hide the rest in a dropdown so it's always accessible, the toggle idea is great.

SMF Tricks - Free & Premium Responsive Themes for SMF.

TwitchisMental

Quote from: Arantor on January 04, 2022, 03:20:19 PMNice - I'd done something similar myself recently.

If I can suggest a couple of possible improvements:

First... CSS variables, something akin to this (have not tested)
Yes this is one of those new things I still need to learn/force myself to use. I have noticed them being used in a few themes. Seems like everything is about saving time nowadays. Noted.

Quote from: Arantor on January 04, 2022, 03:20:19 PMThe other thing is a bit (lot) more fiddly around laying it out on mobile. It will normally wrap to multiple lines which is a bit annoying.

What I did (not the same markup or styling at this but food for thought) was to have the normal breadcrumb trail on desktop... I'd share a link but the site's not open yet.

You cannot see attachments on this board.

With it collapsing by default on mobile...

You cannot see attachments on this board.

And using a widget to expand it vertically when called for...

You cannot see attachments on this board.
Oh that is a fantastic idea. I love what you did for mobile view.

Quote from: Arantor on January 04, 2022, 03:20:19 PMStylewise, well you can see I have Font Awesome loaded but this doesn't make that much odds in the grand scheme of things.

How the toggle is done is by way of an <input type="checkbox"> where the main styling is dropped entirely (appearance: none), then :after is populated with a glyph from Font Awesome and a different glyph is used with :checked on the input box.

The rest of the styling is basically about using :checked as a selector on the input and filtering down the .arrow items thereafter based on 1) a media query and 2) whether or not the checkbox is checked.

It's not a dropin replacement code-wise since SMF doesn't yet have a built in SCSS compiler (I added one to mine), but the relevant styling in case it is of use to anyone:

@media screen and (max-width: 767px) {
.arrowbar {
input ~ .arrow {
display: none;
}

.arrow:first-of-type {
display: block;
}

input:checked ~ .arrow {
display: block;
}

input {
position: absolute;
}

input[type="checkbox"]::after {
content: "\f0c9";
font-family: "Font Awesome 5 Free";
font-weight: 900;
}

.arrow {
padding-left: 50px;
}
}
}
@media screen and (min-width: 768px) {
.arrowbar input {
display: none;
}
}

In case it helps with the relevant placement of the input vs the other elements...

{{#if context.linktree}}
<div class="navigate_section">
<div class="arrowbar">
<input type="checkbox">
{{#each context.linktree}}
<div class="arrow{{#if @last}} active{{/if}}">
{{#if url}}
<a href="{{url}}"><span>{{#if @first}}<i class="fas fa-home fa-fw"></i> {{/if}}{{{name}}}</span></a>
{{else}}
<span>{{{name}}}</span>
{{/if}}
</div>
{{/each}}
</div>
</div>
{{/if}}

Hopefully this will make sense and can be adapted to SMF.
I still have so much to learn. Thank you for all of your input :).

Arantor

Quote from: TwitchisMental on January 04, 2022, 09:06:08 PMSeems like everything is about saving time nowadays. Noted.

Saving time isn't so much the goal here, more saving effort - instead of find/replacing the same colour in a bunch of places, you set it once and just reuse that elsewhere. For Kindred's case for example he'd only need to set the colour once.

I went further down the road and glued in an SCSS parser so I could use variables on a much more extensive basis and have my CSS minified after doing so, but this is not a small change nor for the faint of heart. (It's like an SMF 3.0 level change. But my last site had 6 themes and I wanted to make as much reuse as possible of CSS. When you have SCSS at your control you can do 'include this file' level stuff and variables are everywhere, it made maintaining those so much easier.)

Quote from: TwitchisMental on January 04, 2022, 09:06:08 PMI still have so much to learn. Thank you for all of your input :).

There's always more to learn :) I'm sure you'll be teaching me something soon enough!
No good deed goes unpunished
All helpful urges should be circumvented

Diego Andrés

I attempted mine today with Arantor's idea
I'd say it's okay for a clueless javascript guy like me

You cannot see attachments on this board.

SMF Tricks - Free & Premium Responsive Themes for SMF.

TwitchisMental

Quote from: Diego Andrés on January 06, 2022, 10:49:17 PMI attempted mine today with Arantor's idea
I'd say it's okay for a clueless javascript guy like me

You cannot see attachments on this board.
Looks pretty good :).

Wellwisher

January 07, 2022, 10:14:14 AM #16 Last Edit: January 07, 2022, 10:31:37 AM by Aleksi "Lex" Kilpinen Reason: Lets keep things strictly family friendly. Thank you.
Quote from: Diego Andrés on January 06, 2022, 10:49:17 PMI attempted mine today with Arantor's idea

Defo looks gorgous with the default colour scheme. I would use a location icon instead. Well done.

TwitchisMental

So I have added a small tweak for mobile view, albeit not nearly as cool as what Arantor and Diego have done with theirs XD.

Screenshot -

You cannot see attachments on this board.

Open up the css file again and just add this below the previously added css.  -

@media screen and (max-width: 767px) {
.breadcrumb {
  font: 1em sans-serif;
  list-style: none;
  border: none;
}

.breadcrumb ul {
  display: block;
}

.breadcrumb li {
  display: block;
  width: max-content;
  margin: 5px 0px 5px 0px;
}
}

TwitchisMental

Another small tweak for those who are curious. You can make the final section end flat instead. (Similar to Arantor's example above)
 
Screenshot -

You cannot see attachments on this board.

Find

.breadcrumb li:last-child::after {
    border-left-color: rgb(226, 233, 243);
}

Replace with
.breadcrumb li:last-child::after {
    border: 1px solid transparent;
}

Diego Andrés

Uh yes, I suppose that makes a lot of sense since it's not going anywhere anymore  :laugh:

SMF Tricks - Free & Premium Responsive Themes for SMF.

TwitchisMental

Quote from: Diego Andrés on January 08, 2022, 07:22:10 PMUh yes, I suppose that makes a lot of sense since it's not going anywhere anymore  :laugh:
Works either way, figured I would just give options :D.

Advertisement: