I would like to recreate the style in this Wikipedia Locator map, where there are three distinct styles for boundaries:

  1. Coastline (thin blue line)
  2. High-level administrative land-border (thick grey line)
  3. Low-level administrative land-border (thin grey line)

Wikipedia style Locator map, from https://en.wikipedia.org/wiki/File:France_location_map.svg

I have high and low level administrative units for my area of interest, as polygons. I have tried to match the style as closely as possible:

enter image description here

However, I have no way to distinguish coast-line from land-border. Adding a new coastline polygon would allow me to add a blue line along the coast, but I would still have the grey lines along the coast.

I think that the next step would be to extract only the land-borders from the polygons, but I'm not sure how to do so, other than manually snipping the line wherever it reaches the coast.

Is there a way to 'detect shared boundaries'? Ideally using Processing Toolbox, GRASS, or a QGIS3 Plugin. I am learning to use PyQGIS so would be able to try with that also.

Edit: I have just seen this question: Converting polygon to lines without duplicate edges? It appears what I am trying to do is work with a 'planar graph', which was achieved by using OpenJump.

  • 2
    Natural Earth has all data extracts you need; there are both boundary lines and polygons for Admin level 0 & 1 in Cultural, and ocean polygons or coastline extracts in Physical, among plenty of others in both that might be helpful. E.g. to reproduce that map style, use Admin 1 polygons (+ Admin 0 polygons overlay if you need to mark countries), Ocean polygons and Admin 0 boundaries, in that rendering order and appropriate styling.
    – geozelot
    Aug 7, 2019 at 9:48
  • Thanks - it's a great resource and I like that it provides the land borders as line features: exactly the sort of output I am wanting to create. However I am working with smaller administrative units, which are at a higher resolution than what is available on Natural Earth (specifically New Zealand wards and community boards. Natural Earth only goes as far down as NZ Regional Councils)
    – TimD
    Aug 7, 2019 at 10:21
  • Ah okay, but I think it's still only a matter of proper rendering order of coastlines, Admin 0 boundaries and your own data (where to get that, if you don't have those, you need to find out yourself ,) )
    – geozelot
    Aug 7, 2019 at 10:25

2 Answers 2


I assume you have either an ocean polygon layer or a coastline line layer. If not, you can create one by making a large polygon that covers your entire layer of interest, and use the clip tool to cut holes in it where the land is. Substitute the name of this layer in the expressions where they say 'coastline'.

Coastline (thin blue line)

For the coastline, simply apply a thin blue line style to your coastline layer, or a thin blue boundary line to your ocean polygon layer.

Add three rule-based styles to the administrative areas layer. The first two rules will be the boundaries. The third rule will be the polygon fill.

High-level administrative land-border (thick grey line)

Filter the first rule to the high-level administrative areas. Apply a line geometry generator style using this expression:

difference( boundary( $geometry), buffer(collect('coastline'),42))

Substitute a reasonable, small buffer distance where my expression says 42. Buffer distance is in the same units as the layer's CRS. "Reasonable" depends on the scale of your map and how closely your coastline layer lines up with your administrative boundaries layer. The goal is to clip the entire section of the administrative boundary along the coast, without leaving a noticeable gap.

Apply a thick grey line style.

Low-level administrative land-border (thin grey line)

Filter the second rule to the low-level administrative areas. Use the same geometry generator settings and expression. Apply a thin grey line style.

For the third rule, don't apply a filter. Apply a simple fill style, and set the outline pen type to "no pen."

Explanation of the expression difference( boundary( $geometry), buffer('coastline',42))

  • boundary($geometry) converts the current polygon boundary into a line
  • difference(geometry_a,geometry_b) removes the part of geometry_a that intersects with geometry_b
  • collect('coastline') merges the 'coastline' layer into a single feature. This step is needed because the difference() formula requires a single feature input.
  • buffer('coastline', distance) creates a buffer around the coastline layer, just in case the coastline doesn't exactly match up with the admin boundary.
  • If the 'coastline' layer does match the admin boundary exactly, you could omit the buffer function, and just use difference( boundary($geometry), 'coastline')
  • difference( boundary , buffer('coastline') ) subtracts the buffered coastline from the administrative boundary, leaving only the part of the boundary that isn't on the coast

Using a complicated expression like this in the geometry generator can cause slow rendering, because QGIS has to run all the steps of the expression "on the fly". If you have a problem with slow rendering, you can shave some time off the rendering process by performing some of the steps outside the expression. For example, dissolve the coastline layer into a single feature, clip it to your area of interest, and buffer the result. Omit the buffer function from the expression, and just use this layer. Use it in the coalesce('newlayer') function or by extracting the single feature using geometry(get_feature('newlayer','anyattribute',attributevalue). I'm not sure which method will be faster.

  • I am having difficulty with substituting the 'coastlines' variable in your expression. I have tried substituting with the name as shown in Layers legend, and also with the ID of the layer. Neither have worked. It seems to me the required parameter is a specific feature, rather than a layer?
    – TimD
    Aug 9, 2019 at 3:13
  • 1
    My mistake. The input should indeed be a single feature, not a layer. I'll update my answer.
    – csk
    Aug 9, 2019 at 14:32

I have been able to address this by using different source data. Other administrative boundary files existed, which have the boundaries extending offshore. Using these boundaries, I could clip the boundaries using the coastline, creating perfect land borders, which I could style separately from the coastline.

Administrative unit area polygons with boundaries extending offshore


  1. Polygons to Lines on my administrative units, resulting in boundary lines.
  2. Split with lines splitting the boundary lines with the coastline
  3. Cleaning up the resulting lines by deleting the offshore boundary lines, and Dissolving the remaining lines.
  4. Styling the lines as required.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.