What’s all this about? Check out the introduction blog here.

Introduction

Underlining is a tool under all our belts that allow us to draw attention to particular parts of text and separate them off to others. One use of it is in formatting tool tips. I quite like a style of having a title representing what a particular mark is and then having a list of information about that mark below it, using an underline to represent the two.

(Questionable numbers)

I avoid the built in underlining and personally think that it is better to create a new line under the heading and repeat a character that looks like a solid line (more on how to do this later).

(No thanks)

But if we just have a string of these line-looking characters and add them into out tool tip, it will always be a set length and wont adapt to how long our header is. It is sometimes good formatting, in my opinion, to have underlining that adapts to how long each header is.

So how can we create a custom length string that looks like an underline and add it to a tool tip?

How do

We can split this up into a few steps:

  1. Add a header to a tool tip
  2. Work out the length (how many characters) the header is
  3. Find a character that can make a line if repeated
  4. Repeat this character for the length of the header

1. Add header to tool tip

Drag the field you want as the header to the tooltip box on the marks card

Then click on the same box to edit the tooltip, adding your header to the top and the rest you want to have in there below.

2. Get the length of the string

There’s a calculation to do this in Tableau. Simply create a new calculated field and call len(<your header>). This will return how many characters are in the string that is your header.

3. Find a character to use as a line

There’s an entire see of characters out there that don’t live on your keyboard. Press ⊞ Win + . (Windows) to get a window for viewing lots of characters and emojis (more tips like this on my blog here).

There are a variety of line-like characters that are of interest here. A few:

——— Abc —
–––––– Abc –
_______ Abc _
¯¯¯¯¯¯¯ Abc ¯
‾‾‾‾‾‾‾‾‾ Abc ‾

Abc
———
Abc
––––––
Abc
_______
Abc
¯¯¯¯¯¯¯
Abc
‾‾‾‾‾‾‾‾‾

Be aware that these lines are font dependent and may or not be included in the font you are using. Also be aware that the font of your dashboard may change depending on what fonts are supported wherever you publish it. There are also sometimes bold or italic versions of these characters to play with.

4. Repeat the character for the length of the header

Now we can bring this all together and create the line for our tooltip.

To create the line, you can use another calculated field that returns different length lines based on our other calculated field that found the length of the header.

(updated method)

Thanks to Hesham Eissa and David Sanchez for suggesting this technique after seeing my original method. You can used the space function in Tableau to create a string of spaces as many times as you specify. You can then replace the spaces with whatever character you like, using the replace function. Check it out below:

replace(
    SPACE(
        len( <your header> )
    )
    ,' ','¯'
)

(original method I used)

Tableau doesn’t let you return a string multiplied by how many times you want it and that is why this calculation is a bit ugly. If you want finer control check out the Python script and output at the end.

To finish of, add this underline calculated field to your tooltip where you want it.

Demonstration

I used this underlining technique on the demo dashboard for the top 10 products chart. Notice the underlines are different lengths. I made my underlines longer than the header, rather than the same length, but you can do it however you like.

The calculation is the one shown in step 4.

Here is how I configured the tooltip. It’s essentially: Header, then underline, then extra info.

Notice the different fonts here? I used Courier New in bold and size 10pts for the underline and left the name and extra info as the Tableau defaults. This is the font that worked for me.

Conclusion

And there you have it, what I assume most people will think is a far too complicated method for something that doesn’t matter that much.

But I disagree, custom underlines are a flexible method for drawing attention to where you want it and creating structure. Tooltips are a great example of this but you can use them elsewhere on a dashboard too.

I hope this blog shows clearly how, and why, I created my underlining on my demo dashboard. Please let me know if you have a better way to do this or any feedback/questions. I’ll try reply to comments below, but if not, you can catch my on twitter @chris_vizes.

Appendix

Here’s a nice longer version of the line calculated field I auto generated using a python script. Note: I do not recommend this method after the updated method was added above.

The script

(if you run it you’ll have to be careful with how fonts change between your console and the calculated field input in Tableau.)

for i in range(1,50,1):
    if i == 1:
        print('if [length of product name]<'+str(i))
    else:
        print('elseif [length of product name]<'+str(i))
    print('then '+'"'+'‾'*i+ '"')
print('end')

The output

if [length of header]<1
then "‾"
elseif [length of header]<2
then "‾‾"
elseif [length of header]<3
then "‾‾‾"
elseif [length of header]<4
then "‾‾‾‾"
elseif [length of header]<5
then "‾‾‾‾‾"
elseif [length of header]<6
then "‾‾‾‾‾‾"
elseif [length of header]<7
then "‾‾‾‾‾‾‾"
elseif [length of header]<8
then "‾‾‾‾‾‾‾‾"
elseif [length of header]<9
then "‾‾‾‾‾‾‾‾‾"
elseif [length of header]<10
then "‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<11
then "‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<12
then "‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<13
then "‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<14
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<15
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<16
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<17
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<18
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<19
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<20
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<21
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<22
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<23
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<24
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<25
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<26
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<27
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<28
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<29
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<30
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<31
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<32
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<33
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<34
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<35
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<36
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<37
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<38
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<39
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<40
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<41
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<42
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<43
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<44
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<45
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<46
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<47
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<48
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
elseif [length of header]<49
then "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
end