Styling Map Tips In QGIS


 This started out as trying to answer a gis stackexchange question, and while I didn't find a way to limit the attributes shown in the identify window, this turned out as something worth sharing in a post.

The solution I came up with is styling the map tip, you can do this simple, by using an expression that shows your selected fields in plain text like so:

to_string("name") +'\n' + 'Population: '+to_string("pop_est")

 You can enter this expression either in the display name or in the HTML map tip window, remember that when adding an expression in the HTML map tip window you should either wrap it in square brackets and percent signs like this:

[%to_string("name") +'\n' + 'Population: '+to_string("pop_est")%]


Either way you choose the result in this case ( a simple expression ) will appear as plain text, like this:


 

So how can we style this further?
If we use the HTML map tip window we can add, surprise surprise, HTML code. That means we can use HTML tags to make our text bold, change its color or change its size with a header tag like this:

<h2 style="color:red;">[% to_string("name")%]</h2>
<b>Population: </b>[%to_string("pop_est")%]

We have to remember that fields and expression of other values (it's an expression, you can add any calculation there.


We can style this further, to look like the cover photo if we add a <style> tag at the beginning of the HTML map tip window. We can do something like take the styling rules from W3 Schools CSS Table page and add it there.
After adding the styling rules (you can leave out the rule about hovering over the table rows), we can construct a table with only the fields we want. In the the example I also use the name_ar field and right align it to show the Arabic name of a country written right to left.

<style>
table {
    font-family: Arial, Helvetica, sans-serif;
    font-size: 1.3em;
    border-collapse: collapse;
    width: 300px;
  }
td, th {
    border: 1px solid #ddd;
    padding: 8px;
}
tr:nth-child(even){
    background-color: #f2f2f2;
}
tr:hover {
    background-color: #ddd;
}
th {
    padding-top: 12px;
    padding-bottom: 12px;
    background-color: #04AA6D;
    color: white;
}
</style>
<table>
    <tr>
        <th colspan="2">[% to_string("name")%]</th>
    </tr>
    <tr>
        <th>Field Name</th>
        <th>Value</th>
    </tr>
    <tr>
        <td><b>Population</b></td>
        <td>[%+to_string("pop_est")%]</td>
    </tr>
    <tr>
        <td><b>Continent</b></td>
        <td>[% "continent" %]</td>
    </tr>
    <tr>
        <td><b>Abbreviation</b></td>
        <td>[% "abbrev" %]</td></tr>
    <tr>
        <td><b>Economy</b></td>
        <td>[% "economy" %]</td>
    </tr>
    <tr>
        <td><b>Arabic Name</b></td>
        <td direction="rtl" style="text-align: right;">[% "name_ar" %]</td>
    </tr>
</table>


Using this expression we get the name, the population estimate, the continent, the abbreviation, the economy type and the Arabic name of each country we hover over on the main canvas. We get all of that in a styled table where we define the font, its size, the background color, the width of the map tip and a variety of other styling options that CSS offers.


 

Our result zoomed in looks like this:


 

You can learn HTML and CSS to keep changing and styling your map tips to
help users understand your map better and save time on looking for attributes in the Identify Panel. If this helped you or you want to point out something I've missed feel free to leave a comment.


EDIT

Adding this after a comment asking how can you add a row IF (if ... whatever, doesn't really matter what condition, you decide) so I'm adding an example about it.

I'm going to edit the population row to show only if the "pop_est" field has more than 10,000 (basically ruling out Antarctica).
The secret here is using a simple expression that returns a string with the entire row if the condition is met ("pop_est" >10000) or an empty string if not.

I'll add it above the Population row we already have and color the text red so it's easier to tell. Right below the header line I'll insert an expression (either with expression dialog or just write it between square brackets and precent signs).

    if( "POP_EST" > 100000,
            '<tr><td><b style="color:red;">Population</b></td><td>'+
            to_string( "POP_EST") +
            '</td></tr>',
        '')

The expression is pretty simple, it uses only the if function and concatenates strings with the plus (+) sign, make sure to note the open and closed single quatation mark after the last comma, that's the third argument of the if function which takes 1. condition, 2. what to return if true, 3. what to return if false.

We can now see a second population row in most map tips, but over Antarctica we still get the same map tip.

 

 

 

The new map tip code lloks like this (without the <style> part which stayed the same)

<table>
    <tr>
        <th colspan="2">[% to_string("name")%]</th>
    </tr>
    <tr>
        <th>Field Name</th>
        <th>Value</th>
    </tr>
    [%if( "POP_EST" > 100000,'<tr><td><b style="color:red;">Population</b></td>'+'<td>'+  to_string( "POP_EST") +'</td></tr>','')%]
    <tr>
        <td><b>Population</b></td>
        <td>[%+to_string("pop_est")%]</td>
    </tr>
    <tr>
        <td><b>Continent</b></td>
        <td>[% "continent" %]</td>
    </tr>
    <tr>
        <td><b>Abbreviation</b></td>
        <td>[% "abbrev" %]</td></tr>
    <tr>
        <td><b>Economy</b></td>
        <td>[% "economy" %]</td>
    </tr>
    <tr>
        <td><b>Arabic Name</b></td>
        <td direction="rtl" style="text-align: right;">[% "name_ar" %]</td>
    </tr>
</table>





Comments

  1. Hi I want to display images from a folder from local drive .
    Each point of the shape file has a different set of images.
    I want each image to be displayed on the maptip one after another.
    Tried HTML but no use and php& JS are not supported.
    please help - badshah.khan424@gmail.com

    ReplyDelete
    Replies
    1. Hi Badash,
      your comment got me looking into this so I wrote a new post with the solution
      https://bogind.blogspot.com/2022/09/avanced-styling-map-tips-in-qgis.html
      Thanks for the idea

      Delete
  2. This works really well for me until I have NULL values where I'd like to suppress the row in the table. Not being an HTML/CSS guru I can't find a way to do that since HTML seems not to have been designed to cope with an if-then-else construct. Any hints? TIA

    ReplyDelete
    Replies
    1. Look at the new edit at the end, you can do this with expressions

      Delete

Post a Comment