Loading...

Top
PFQ Banner

This is PokéFarm Q, a free online Pokémon collectables game.

Already a user? New to PFQ?

Single post in Free CSS, Userscripts, etc

Forum Index > Other > Other Art > Free CSS, Userscripts, etc >

DrWho's AvatarDrWho
DrWho's Avatar
A good friend asked if I could post this code from several years ago, please find it below.

Creating an arrow interface

In this post I'm going to give a rundown on how to create a tabbed interface that you can navigate with arrows. If you like, you can open a template editor and build it as we go.

Basic setup

We're going to start off with a tabbed_interface and some code that is not yet relevant to the arrow interface.
[sc=tabbed_interface horizontal] [ul] [li]One[/li] [li]Two[/li] [li]Three[/li] [li]Four[/li] [/ul] [sc=tab]Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam placerat tempor felis vitae consequat. Donec at sapien sapien. Nulla lectus ipsum, ultricies id maximus eget, luctus id tellus.[/sc] [sc=tab]Donec pellentesque ligula sit amet purus efficitur suscipit. Nunc nisi arcu, vulputate vel tortor et, volutpat malesuada lorem.[/sc] [sc=tab]Etiam fermentum erat ac ultrices elementum. Ut at nibh justo. Vestibulum odio orci, sodales eu sapien et, consequat viverra risus.[/sc] [sc=tab]Duis posuere sem enim, sit amet iaculis purus accumsan finibus. Proin ante arcu, ullamcorper a neque in, tempor ultricies metus. Donec at ipsum interdum, elementum mauris quis, efficitur dolor.[/sc] [/sc] [style] /* ignore whitespace between elements */ .tabbed_interface { white-space: nowrap; &>ul>li, &>div { white-space: pre-line; } } /* reset styles */ .tabbed_interface, .tabbed_interface > ul, .tabbed_interface > ul > li, .tabbed_interface > div { padding: 0; margin: 0; background: none; box-shadow: none; border: none; border-radius: 0; } [/style]
We set white-space: nowrap on .tabbed_interface to collapse all newlines. This allows for nicer formatting of your post, you can separate [sc=tab]The first tab[/sc] [sc=tab]The second tab[/sc] into several lines without actually pushing the second tab a line down. However, this also squishes all text into a single line. To prevent this, we set white-space: pre-line on ul>li and div which is where our text lives. The result is that line breaks are ignored between elements and preserved within content sections. Additionally, we also strip all elements of the .tabbed_interface off their padding, margin, borders, shadows and colours so we can start with a blank slate. If you preview this now, you'll end up with a barren tabbed_interface. Our next task is to add the arrows.

Setting up the grid

For the next task, we're going to turn the ul into a css grid by adding the following style.
/* set up the grid */ .tabbed_interface > ul { display: grid; grid-template-columns: 1fr 66% 1fr; }
ul is now a grid made up of three columns. First, the centre column is given 66% of the available width. The left and right column are given an equal fr value, which means that all remaining width is shared equally between them. To illustrate, you could have written this as 17% 66% 17%. The benefit of CSS grid in this situation is that we can place items into grid cells explicitly. Our goal is to place the li corresponding to the 'previous' tab in the left cell, the li of the 'current' tab in the centre cell and the li of the 'next' tab in the right cell. How do we identify the 'previous', 'current' and 'next' li?

Placing items

/* previous tab */ .tabbed_interface > ul > li { grid-row: 1; grid-column: 1; z-index: 1; }
There is no distinguishing class for the 'previous' tab. What we will do is the style above which applies to all li, and then have the 'current' and 'next' tab override that style as needed. The style places all li at column row 1 column 1 in the grid. Assigning a z-index allows multiple li to stack in the same grid cell.
/* current tab */ .tabbed_interface > ul > li.tab-active { grid-column: 2; } /* next tab */ .tabbed_interface > ul > li.tab-active + li { grid-column: 3; }
Next, we identify the 'current' tab through its .tab-active class and place it in the centre column. Lastly, we identify the 'next' tab through a sibling combinator as li.tab-active + li. That means "the tab immediately following .tab-active". We place it in the third and rightmost column.
/* tabs beyond the next tab */ .tabbed_interface > ul > li.tab-active + li ~ li { display: none; }
Any tabs beyond the 'next' tab can be identified through yet another sibling combinator. li.tab-active + li ~ li means "all li following the li immediately following li.tab-active". In our layout, we only care about the 'previous', 'current' and 'next' tab so we choose not to display those beyond. If we don't do this, they will stack on the left and cover the 'previous' arrow. To recap, we now have a column on the left where all tabs before the 'current' tab stack. The 'previous' tab is on top of that stack and therefore clickable. The 'current' tab is in the centre and the 'next' tab is on the right. Our next modification is going to be replacing the titles of the 'previous' and 'next' tabs with a left and right arrow respectively.

Arrows

To insert the arrows, let's revise the styles for the 'previous', 'current' and 'next' tab.
/* previous tab */ .tabbed_interface > ul > li { grid-row: 1; grid-column: 1; z-index: 1; font-size: 0; &:before { font-size: 1rem; content: "←" } }
Note that we've added a :before element with the content value "←". If the tab previously read 'About', it will now read '←About'. Next, we set the font-size of li to 0 which removes all text. The :before element overrides this with a font-size of 1rem. Continuing the example above, 'About' lives in li while '←' lives in li:before. We've essentially replaced the content of the 'previous' tab with an arrow.
/* current tab */ .tabbed_interface > ul > li.tab-active { grid-column: 2; font-size: 1rem; &:before { display: none; } }
Remember that we have to override the style for the 'current' and 'next' tab as needed. In the current tab, we want the title to display, but the arrow to not display.
/* next tab */ .tabbed_interface > ul > li.tab-active + li { grid-column: 3; &:before { content: "→" } }
The adjustment for the 'next' tab is that we want the content in :before to be a right arrow and not a left arrow. Now we have a fully functional navigation interface. The 'previous' tab is on the left with its title replaced with an arrow, the 'current' tab is in the centre and the 'next' tab is on the right with its title replaced with an arrow. All that's left to do is to style our interface.

The result

  • One
  • Two
  • Three
  • Four
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam placerat tempor felis vitae consequat. Donec at sapien sapien. Nulla lectus ipsum, ultricies id maximus eget, luctus id tellus.
Donec pellentesque ligula sit amet purus efficitur suscipit. Nunc nisi arcu, vulputate vel tortor et, volutpat malesuada lorem.
Etiam fermentum erat ac ultrices elementum. Ut at nibh justo. Vestibulum odio orci, sodales eu sapien et, consequat viverra risus.
Duis posuere sem enim, sit amet iaculis purus accumsan finibus. Proin ante arcu, ullamcorper a neque in, tempor ultricies metus. Donec at ipsum interdum, elementum mauris quis, efficitur dolor.
Building on the code above, I've added some style for colours, padding and alignment. Lastly, I'd like to mention that not every browser supports every feature of CSS. For instance, our template uses CSS grid which may not be available in old browsers. One option for our template to fail gracefully would be to only replace titles with arrows when the browser supports flex. Unfortunately, this requires a feature query which the PFQ parser does not seem to allow. However, we can fall back on flex to ensure the 'current' tab is adequately large when the browser does not support grid.
Avatar by Kaelwolfur. Sent from my PokéNav
© PokéFarm 2009-2024 (Full details)Contact | Rules | Privacy | Reviews 4.6★Get shortlink for this page