Set Layer Opacity and Blend Modes in PyQGIS

Transparency in QGIS is not one setting. There is the opacity of the whole rendered layer, the alpha channel of a symbol's colour, the opacity of an individual symbol layer, and — separate from all three — the blend mode that decides arithmetic rather than mixing. Choosing the wrong one produces a map that is nearly right and stubbornly refuses to be fixed by adjusting a number.

This recipe belongs to Symbol Layers & Advanced Symbology in PyQGIS. It covers each level from Python, the blend modes worth knowing by name, the difference between layer blending and feature blending, and what happens to all of it when the map is exported to PDF.

Where transparency is applied in the render pipelineColour alpha applies as each primitive is painted, so overlapping features accumulate and read darker. Symbol layer and symbol opacity apply to that symbol's own output. Layer opacity applies once to the finished flattened layer, so overlaps within the layer do not accumulate.Overlaps accumulate — unless the fade is applied lastcolour alpha, per primitivewhere three overlap it is nearly solidlayer opacity, applied oncethe layer is flattened, then faded evenlysame three circles, same 40 percent, two different maps

Prerequisites

  • QGIS 3.34 LTR (bundled Python 3.12) or newer.
  • At least two overlapping layers if you want to see blend modes do anything — the canonical pair is a hillshade under a thematic fill.
  • A basic stacked symbol; see stacking symbol layers if the layers in a symbol are new to you.

Layer opacity: fade the finished render

The simplest control fades everything the layer drew, after it drew it.

from qgis.core import QgsProject

layer = QgsProject.instance().mapLayersByName("landuse")[0]
layer.setOpacity(0.55)
layer.triggerRepaint()

Breakdown: setOpacity() takes a float from 0 to 1 and applies to the layer's composited output, so a polygon that overlaps another polygon in the same layer does not double up. That property is exactly what you want for a thematic wash over a basemap, and exactly what you do not want when the overlap itself carries meaning. Note that this replaced the older setLayerTransparency(int) — a percentage, and inverted — which was removed in QGIS 3.

Raster layers use the same call, but their renderer also has an opacity, and the two multiply:

raster = QgsProject.instance().mapLayersByName("hillshade")[0]
raster.renderer().setOpacity(0.8)
raster.setOpacity(0.9)                # net 0.72

Breakdown: Setting both is legal and almost always a mistake, because the number you tune afterwards is not the number you see. Pick one — the layer for a simple fade, the renderer when a specific band's rendering needs to be dialled back independently of the layer.

Colour alpha: fade each drawn shape

When overlaps should accumulate, put the transparency in the colour instead.

from qgis.PyQt.QtGui import QColor

colour = QColor("#2563eb")
colour.setAlphaF(0.35)
layer.renderer().symbol().setColor(colour)
layer.triggerRepaint()

Breakdown: setAlphaF() takes 0–1; setAlpha() takes 0–255, and mixing them up is the reason a symbol occasionally comes out invisible. Because the alpha is on the brush, each drawn feature blends with whatever is already on the canvas — including earlier features from the same layer. Density maps of overlapping buffers rely on this, and it is a genuinely different picture from the same value applied as layer opacity.

symbol.setOpacity(0.35) sits between the two: it fades the whole symbol including all of its symbol layers, but still per feature, so overlaps still accumulate.

Blend modes: arithmetic, not mixing

A blend mode replaces "put this on top" with a per-channel calculation between the incoming pixel and what is already there.

from qgis.PyQt.QtGui import QPainter

thematic = QgsProject.instance().mapLayersByName("landuse")[0]
thematic.setBlendMode(QPainter.CompositionMode_Multiply)
thematic.triggerRepaint()

Breakdown: Multiply darkens: each channel is multiplied, so white leaves the underlying pixel alone and anything darker shades it. Laid over a hillshade this produces relief-shaded thematic mapping with no manual work, and it is the reason Multiply is by far the most used mode in QGIS. Screen is the inverse and lightens; Darken and Lighten pick the extreme per channel rather than combining; Overlay and SoftLight boost contrast and are worth trying when Multiply makes a map too heavy.

The same call exists at symbol-layer level, which is how one layer of a stack can multiply onto the layer beneath it inside a single symbol:

from qgis.core import QgsProject

symbol = thematic.renderer().symbol()
symbol.symbolLayer(1).setRenderingPass(1)
thematic.setFeatureBlendMode(QPainter.CompositionMode_Darken)

Breakdown: setFeatureBlendMode() blends features of this layer against each other rather than against the layers below, which is the tool for showing where features of one layer overlap without them also darkening the basemap. setRenderingPass() shifts a symbol layer into a later pass so it draws after every feature's earlier passes, which is how a casing can be drawn under all the roads rather than under each road individually — the fix for the classic "roads casing cuts across the junction" artefact.

Multiply is the mode that reveals reliefThe same coloured fill sits over the same shaded relief. With normal compositing the fill covers the relief entirely. With multiply the relief shows through as shading within the colour. With screen the result lightens and the relief is present but washed out.Same two layers, three compositing rulesNormalthe relief is goneMultiplycolour plus shadingScreenpresent but washed outmultiply leaves white untouched, which is why it works over a hillshade

Choosing between the four levels

Written as a decision, the choice is short.

If the whole layer should sit back so something beneath it reads through, use layer opacity. If overlapping features within the layer should build up — overlapping buffers, stacked catchments, repeated GPS tracks — use colour alpha. If one part of a stacked symbol should fade while the rest stays solid, use symbol-layer opacity. If the effect you want is shading, tinting or contrast rather than transparency at all, you want a blend mode and no opacity anywhere.

A worked case makes the distinction concrete. Say a flood-extent layer must show both where water reaches and how many scenarios agree. Layer opacity gives a uniform blue wash that answers the first question and destroys the second. Colour alpha at 25 percent answers both: one scenario is faint, four overlapping scenarios are strong, and the reader gets a density map for free. Add Multiply on top of a hillshade and the same layer also shows the terrain the water is sitting in — three pieces of information from one fill, and none of them needed a second layer.

from qgis.PyQt.QtGui import QColor, QPainter

water = QColor("#2563eb")
water.setAlphaF(0.25)
flood.renderer().symbol().setColor(water)
flood.setBlendMode(QPainter.CompositionMode_Multiply)
flood.setOpacity(1.0)
flood.triggerRepaint()

Breakdown: Leaving setOpacity(1.0) explicit is worth the line — it documents that the fade is deliberately in the colour, and it resets the layer if an earlier experiment left an opacity behind. The order of the three calls does not matter, because none of them render; only triggerRepaint() does, and it should be the last statement in any styling block for exactly that reason.

The export caveat

Blend modes other than SourceOver cannot be expressed in PDF or SVG. QGIS deals with this by rasterising any layer that uses one, which means a print layout containing a multiplied fill exports a raster tile for that layer while everything else stays vector.

from qgis.core import QgsLayoutExporter

settings = QgsLayoutExporter.PdfExportSettings()
settings.rasterizeWholeImage = False
settings.forceVectorOutput = True

Breakdown: forceVectorOutput = True asks QGIS to keep vectors where it can, but it cannot override the blend-mode rule — the affected layer still rasterises, and the rest of the layout stays sharp. rasterizeWholeImage = True is the blunt alternative that flattens everything, producing a file that always matches the canvas at the cost of selectable text and scalable line work. When crisp vector output matters more than the effect, bake the shading into the data instead: multiply the hillshade into the thematic raster once with the raster calculator and style the result normally.

QGIS version compatibility

The examples target QGIS 3.34 LTR (Python 3.12).

QGIS versionPythonNotes
3.16 LTR3.7setOpacity() on layers, setBlendMode() and setFeatureBlendMode() all present.
3.22 LTR3.9Layout export settings expose forceVectorOutput and rasterizeWholeImage.
3.28 LTR3.9Raster renderer opacity independent of layer opacity.
3.34 LTR3.12Baseline for this page.
3.40+3.12Blend modes selectable on individual symbol layers in the GUI as well as the API.

Troubleshooting

  • Overlaps look solid when you wanted a wash. Colour alpha is accumulating. Move the transparency to layer.setOpacity().
  • The wash is uniform when you wanted density. The reverse — move the transparency into the colour with setAlphaF().
  • A symbol vanished entirely. setAlpha(0.35) was used instead of setAlphaF(0.35); on the 0–255 scale, 0.35 rounds to zero.
  • Multiply has no visible effect. There is nothing beneath the layer to multiply with, or the layer below is also using a blend mode and the order is fighting you. Check the layer tree order.
  • The PDF has a fuzzy patch where one layer was. That layer uses a blend mode and was rasterised. Bake the effect into the data or accept the raster.
  • Opacity does not stick after reopening the project. The change was made on a layer object that was replaced on reload. Set it in a project-loaded hook, or save the style with the project.

Conclusion

Use layer.setOpacity() to fade a finished layer evenly, colour alpha when overlaps should accumulate, and setBlendMode(QPainter.CompositionMode_Multiply) to shade a thematic fill with relief. Remember that any blend mode other than the default forces that layer to rasterise on PDF and SVG export, and bake the effect into the data when vector output matters more.

Frequently Asked Questions

What is the difference between blend mode and feature blend mode? Blend mode composites this layer against everything already drawn beneath it. Feature blend mode composites this layer's own features against each other before the layer as a whole is composited. Use the second when you want to show self-overlap without darkening the basemap.

Can I set a blend mode on one symbol layer only? Yes — symbol_layer.setBlendMode() — and it composites that layer against the earlier layers of the same symbol. It is the neatest way to make a highlight glow blend into its own casing without affecting the map beneath.

Why does my hillshade look grey rather than shaded? The thematic layer above it is opaque and using normal compositing. Set its blend mode to Multiply; leave the hillshade itself fully opaque underneath.

Does opacity affect the legend? No. Legend patches are drawn at full strength, which is usually desirable but does surprise people producing a faded overlay. If the legend must match, render the patch yourself or apply the alpha to the symbol colour rather than the layer.