Pet profile tab sections

This tutorial will show you how to make each section in your pet profile its own "page" so-to-speak, letting you link to the story, treasure, stats etc separately. Start with a blank pet profile, and you can copy-and-paste the code samples in each part to follow along with the tutorial.

This tutorial will try to teach the core concepts instead of any specific layout or aesthetic. The hope is that once you understand how it works, you'll be able to apply it to all sorts of profiles however you like.

Here's a screencast of what this tutorial will walk you through making! In retrospect, I should've given this pet a minion and some TC items so the sections aren't just empty... but oh well. From experience, we learn :)


01. Finding the section IDs

For the sake of this tutorial, let's say that these are the pages we want to have on the profile:

  1. Minion
  2. Pet overlay, name, and information (Let's show this one by default)
  3. Pet stats
  4. Story/description
  5. Treasure
  6. Pet friends

Each of these sections has a CSS ID, which is what we'll use to link to it and style it. This is something Subeta's code provides; you just need to find it. To figure out what each section's ID is, we view the page source and look at the HTML for each section. An easy way to home in on a section's HTML is to right-click it and choose "Inspect Element". For example, here is a screenshot of me using the Inspector to look at the source code of the page:

And bingo! This is the part that tells us what we need to know:

If you hover over each of those sections, it will highlight the corresponding section in the page. We can see each section's div has a corresponding ID:

  1. Minion - ID is #column_1
  2. Pet overlay, name, and information - ID is #column_2
  3. Pet stats - ID is #column_3
  4. Story/description - ID is #pet_desc
  5. Treasure - ID is #pet_treasure
  6. Pet friends - ID is #pet_friends

Note: When we refer to an ID, we use a hashtag (#) in the front to sort of say "this is an ID we are talking about". This is similar to how dots (.) are usually used for CSS classes.

Great! This is information that will really come in handy later, so we'll make a note of this and move on.


02. Linking to a section

Now that we know our section IDs, we can now write links to them! You are probably used to seeing HTML links (anchor tags) that look like this:

<a href="https://subeta.net/">This is a link!</a>

You might have also seen anchor tags that look like this:

<a href="#blah">This is another link!</a>

What the second type links to is a section or anchor within a page. Nowadays, the preferred way to use it is to link to a CSS ID: the same IDs we figured out for everything in step 01. So for instance, to link to the treasure section, we would write:

<a href="#pet_treasure">Treasure</a>

Go ahead and try putting that on your pet profile. If you click this link, you'll notice that it takes you to the same URL but with #pet_treasure stuck onto the end. And of course, you'll notice that nothing changes on the page as a result... yet. That's where the :target selector comes into play.


03. Crash course: the :target selector

The best way to understand the :target selector is to see it in action! Go ahead and paste this code in your pet profile:

<style type="text/css">
  #pet_treasure { border: 3px solid #111; }
  #pet_treasure:target { border: 3px solid #f77; }
</style>

<a href="#pet_treasure">Pet Treasure</a>

Now, go to your pet profile. You should see a dark black border around your Pet Treasure. Now, click the link that says Pet Treasure. The border should change to red.

Let's break down how the code does this. First, we have this line of CSS:

#pet_treasure { border: 3px solid #111; }

This is what makes a black border around the pet treasure by default. #pet_treasure selects the treasure box, and the border rule gives it a black border. This line of CSS just says, "find the div with the id pet_treasure, and give it a black border."

The next line is what gives it a red border.

#pet_treasure:target { border: 3px solid #f77; }

Here, instead of selecting #pet_treasure, we selected #pet_treasure:target. What that means is, "If there is a #pet_treasure on the end of the URL, use this CSS! Otherwise, ignore this CSS."

Therefore, if we go to https://subeta.net/pets/PetName then we'll see a gray border. But if we click the link and go to https://subeta.net/pets/PetName#pet_treasure, it will activate the special :target rule and show a red border instead. Here's a screenshot that demonstrates this in action. Pay attention to the URL in the address bar:

Now that you know how :target works, the next step is using it to make the profile show one page at a time.


04. Toggling visibility with :target

First, we decided that the basic info (overlay, pet name, etc) is what we're going to show by default. That section's CSS ID is #column_2. So let's start by writing some CSS to show just that, and hide everything else, like this:

<style type="text/css">
  #column_2 { visibility: visible; }
  #column_1, #column_3, #pet_desc, #pet_treasure, #pet_friends { visibility: hidden; }
</style>

The first line will force #column_2 to show, while the second line will hide everything else. Next, let's add some CSS to show everything else when it is targeted.

<style type="text/css">
  #column_2 { visibility: visible; }
  #column_1, #column_3, #pet_desc, #pet_treasure, #pet_friends { visibility: hidden; }
  #column_1:target, #column_2:target, #column_3:target, #pet_desc:target, #pet_treasure:target, #pet_friends:target { visibility: visible; }
</style>

That 3rd line of CSS we added basically says: "For alllll of these divs, make sure they are displayed if they're being targeted!"

Now, if you paste this into your profile, you can see that it almost works. If you stick an ID onto the URL, indeed that is the section that shows up...

...except we've made #column_2 show up no matter what. Unfortunately, there is no way to simply hide #column_2 when something else is being targeted. Therefore, our workaround will be to position the other sections on top of #column_2. That way, #column_2 will be visible when nothing else is targeted. When another page is being targeted, #column_2 will be behind it and won't be visible. To do this, we need to position everything on top of each other, which brings us to the last step of the tutorial...


05. Positioning the layout components

This last step is going to be in two parts: 1) creating and positioning a navigation menu and 2) positioning the individual sections of the layout (the six pages we have IDs for). CSS positioning is tricky enough to deserve its own tutorial so I won't go too in depth about it here. Further, I will recommend you use my personal reset code which will take care of the basic "resetting" of the profile (hiding the header and sidebar, etc) to give you a clean base to work off of.

@import url('https://bug.bz/subeta/css/reset/pet.css');

The navigation menu

First, we will create a little div that contains links to each section. Let's give this div a class so we can easily style it with CSS. You can name it anything you like; I'm going to call it .navigation-links as a clear, descriptive name.

<div class="navigation-links">
<a href="#column_1">Minion</a>
<a href="#column_2">Pet info</a>
<a href="#column_3">Stats</a>
<a href="#pet_desc">Story</a>
<a href="#pet_treasure">Treasure</a>
<a href="#pet_friends">Friends</a>
</div>

Next, let's add a little CSS to just fix it to the top of our page:

.navigation-links { position: fixed; top: 0; visibility: visible; }

Finally, let's just add a few basic styles: we'll give it a fixed height and space out the links. Then, we'll add some top padding to the entire web page so it doesn't overlap the content of the page.

.navigation-links { position: fixed; top: 0; visibility: visible; height: 60px; }
.navigation-links a { display: inline-block; margin-left: 5px; margin-right: 5px; }
body { padding-top: 60px; }

At this point, your profile code in its entirety should look like this:

<style type="text/css">
  @import url('https://bug.bz/subeta/css/reset/pet.css');
  #column_2 { visibility: visible; }
  #column_1, #column_3, #pet_desc, #pet_treasure, #pet_friends { visibility: hidden; }
  #column_1:target, #column_2:target, #column_3:target, #pet_desc:target, #pet_treasure:target, #pet_friends:target { visibility: visible; }

  .navigation-links { position: fixed; top: 0; visibility: visible; height: 60px; }
  .navigation-links a { display: inline-block; margin-left: 5px; margin-right: 5px; }
  body { padding-top: 60px; }
</style>

<div class="navigation-links">
<a href="#column_1">Minion</a>
<a href="#column_2">Pet info</a>
<a href="#column_3">Stats</a>
<a href="#pet_desc">Story</a>
<a href="#pet_treasure">Treasure</a>
<a href="#pet_friends">Friends</a>
</div>

If you look at the profile now, you'll see a bunch of links along the top. Kind of ugly, but they work and can always be prettied up later. Clicking the links will cause different profile sections to show.

The profile sections

Our final task is to make the profile sections look how we want. At this step, there are a lot of possibilities and even very sophisticated things you can do, but for the sake of this tutorial, we will simply give them a fixed size and stack them using absolute positioning.

First, we notice that the direct parent container of these six is #pet_info. We can establish this parent container as reference frame by giving it a relative positioning. Any positioning will do; it simply needs to have a position set. Again, this deserves its own tutorial, but will also make more sense once you see it in practice.

Let's arbitrarily decide we want each page to be 500px by 500px too. We'll set this as the size of the parent container - that way, we just set it once, and we can tell the six children to expand to fill the parent.

#pet_info { position: relative; width: 500px; height: 500px; }

Next, let's style the six children. First, let's add a background color and border to each one.

#column_1, #column_2, #column_3, #pet_desc, #pet_treasure, #pet_friends { border: 3px solid #111; background-color: #eee; }

Finally, we do some magic with absolute positioning. Here's what the CSS will look like, followed by a bulleted explanation of each part:

On all six sections:

#column_1, #column_2, #column_3, #pet_desc, #pet_treasure, #pet_friends {
  border: 3px solid #111; background-color: #eee;
  position: absolute; top: 0; left: 0;
  width: 100%; height: 100%;
  overflow: auto;
}

On all sections except for #column_2

#column_1, #column_3, #pet_desc, #pet_treasure, #pet_friends { visibility: hidden; z-index: 9999; }
  • position: absolute; top: 0; left: 0; - When we set absolute positioning on these elements, they're going to be positioned relative to #pet_info. The top and left values represent their position inside of the #pet_info div.
  • width: 100%; height: 100%; - These ensure that each section will have the same size as #pet_info. The value 100% means "100% of what #pet_info has"
  • overflow: auto; - We declared the height to be 100%, but the contents could be bigger than that. So this ensures that if the content overflows, the page will scroll.
  • z-index: 9999; - This is done on everything EXCEPT for #column_2 because we want the other sections to layer on top of it.

Are you ready? This is the final, entire profile code:

<style type="text/css">
  @import url('https://bug.bz/subeta/css/reset/pet.css');
  #column_2 { visibility: visible; }
  #column_1, #column_3, #pet_desc, #pet_treasure, #pet_friends { visibility: hidden; z-index: 9999; }
  #column_1:target, #column_2:target, #column_3:target, #pet_desc:target, #pet_treasure:target, #pet_friends:target { visibility: visible; }

  .navigation-links { position: fixed; top: 0; visibility: visible; height: 60px; }
  .navigation-links a { display: inline-block; margin-left: 5px; margin-right: 5px; }
  body { padding-top: 60px; }

  #pet_info { position: relative; width: 500px; height: 500px; }
  #column_1, #column_2, #column_3, #pet_desc, #pet_treasure, #pet_friends {
    border: 3px solid #111; background-color: #eee;
    position: absolute; top: 0; left: 0;
    width: 100%; height: 100%;
    overflow: auto;
  }
</style>

<div class="navigation-links">
<a href="#column_1">Minion</a>
<a href="#column_2">Pet info</a>
<a href="#column_3">Stats</a>
<a href="#pet_desc">Story</a>
<a href="#pet_treasure">Treasure</a>
<a href="#pet_friends">Friends</a>
</div>

A pet story can go here!

I hope this tutorial helped! If you have any questions, don't hesitate to ask.