[{"data":1,"prerenderedAt":1727},["ShallowReactive",2],{"doc:\u002Fpyqgis-cartography-visualization\u002Flabeling-and-annotations\u002Fformat-label-buffers-backgrounds-and-shadows-pyqgis":3},{"id":4,"title":5,"body":6,"description":1716,"extension":1717,"meta":1718,"navigation":275,"path":1723,"seo":1724,"stem":1725,"__hash__":1726},"docs\u002Fpyqgis-cartography-visualization\u002Flabeling-and-annotations\u002Fformat-label-buffers-backgrounds-and-shadows-pyqgis\u002Findex.md","Format Label Buffers, Backgrounds and Shadows in PyQGIS",{"type":7,"value":8,"toc":1703},"minimark",[9,13,35,44,175,180,201,205,211,436,450,454,457,578,595,679,683,686,941,966,970,973,1187,1207,1309,1313,1316,1504,1536,1540,1573,1577,1618,1622,1625,1629,1639,1653,1659,1665,1669,1699],[10,11,5],"h1",{"id":12},"format-label-buffers-backgrounds-and-shadows-in-pyqgis",[14,15,16,17,21,22,25,26,29,30,34],"p",{},"A label that reads perfectly over a plain background disappears over an aerial photo, a hillshade or a dense street network. Cartographers solve this with three tools: a ",[18,19,20],"em",{},"buffer"," (a halo of contrasting colour hugging the letters), a ",[18,23,24],{},"background"," (a shape behind the text, from a subtle rounded box to a road shield), and a ",[18,27,28],{},"shadow"," (a soft offset that lifts the text off the map). All three live on ",[31,32,33],"code",{},"QgsTextFormat",", the object that describes how text looks everywhere in QGIS — labels, layout items, annotations and legend text alike.",[14,36,37,38,43],{},"This recipe belongs to ",[39,40,42],"a",{"href":41},"\u002Fpyqgis-cartography-visualization\u002Flabeling-and-annotations\u002F","Labeling & Annotations in PyQGIS",". It builds a text format with each of the three effects, shows when each one is the right choice, drives colours from data, adds rich text with HTML, and saves the result as a named text format so every layer and layout can reuse it.",[14,45,46],{},[47,48,53,57,61,68,77,113,132,157],"svg",{"viewBox":49,"role":50,"ariaLabel":51,"xmlns":52},"0 0 760 300","img","The same label over a busy aerial background four ways: plain text disappearing, a light buffer halo making it readable, a rounded background box making it prominent, and a shadow lifting it slightly","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[54,55,56],"title",{},"Four treatments of one label",[58,59,60],"desc",{},"Four panels with a mottled green and brown background suggesting aerial imagery. Panel one shows plain dark text, readable only where the background happens to be light. Panel two shows the same text with a thin pale halo, readable everywhere. Panel three shows the text in a rounded pale box with a thin outline, readable and strongly emphasised. Panel four shows the text with a soft grey shadow offset down and right.",[62,63],"rect",{"x":64,"y":64,"width":65,"height":66,"fill":67},"0","760","300","#f6f3ea",[69,70,76],"text",{"x":71,"y":72,"style":73,"fill":74,"textAnchor":75},"380","28","text-anchor:middle;font-size:14px;font-weight:bold;font-family:sans-serif","#17211d","middle","Readability over a busy background",[78,79,80,88,95,101,107],"g",{},[62,81],{"x":82,"y":83,"width":84,"height":85,"rx":86,"fill":87},"24","52","166","200","10","#c9d6cf",[89,90],"circle",{"cx":91,"cy":92,"r":93,"fill":94},"70","110","30","#a7b1ab",[89,96],{"cx":97,"cy":98,"r":99,"fill":100},"150","180","40","#b0a488",[69,102,106],{"x":103,"y":104,"style":105,"fill":74,"textAnchor":75},"107","160","text-anchor:middle;font-size:16px;font-weight:bold;font-family:sans-serif","Oakfield",[69,108,112],{"x":103,"y":109,"style":110,"fill":111,"textAnchor":75},"276","text-anchor:middle;font-size:10.5px;font-family:sans-serif","#2f3b35","plain",[78,114,115,118,121,124,130],{},[62,116],{"x":117,"y":83,"width":84,"height":85,"rx":86,"fill":87},"204",[89,119],{"cx":120,"cy":92,"r":93,"fill":94},"250",[89,122],{"cx":123,"cy":98,"r":99,"fill":100},"330",[69,125,106],{"x":126,"y":104,"style":127,"fill":74,"stroke":128,"strokeWidth":129,"textAnchor":75},"287","text-anchor:middle;font-size:16px;font-weight:bold;font-family:sans-serif;paint-order:stroke;stroke-linejoin:round","#fffdf7","4",[69,131,20],{"x":126,"y":109,"style":110,"fill":111,"textAnchor":75},[78,133,134,137,140,143,152,155],{},[62,135],{"x":136,"y":83,"width":84,"height":85,"rx":86,"fill":87},"384",[89,138],{"cx":139,"cy":92,"r":93,"fill":94},"430",[89,141],{"cx":142,"cy":98,"r":99,"fill":100},"510",[62,144],{"x":145,"y":146,"width":147,"height":148,"rx":149,"fill":128,"stroke":150,"style":151},"417","142","100","26","6","#59645f","stroke-width:1.2",[69,153,106],{"x":154,"y":104,"style":105,"fill":74,"textAnchor":75},"467",[69,156,24],{"x":154,"y":109,"style":110,"fill":111,"textAnchor":75},[78,158,159,163,166,169,173],{},[62,160],{"x":161,"y":83,"width":162,"height":85,"rx":86,"fill":87},"564","172",[89,164],{"cx":165,"cy":92,"r":93,"fill":94},"610",[89,167],{"cx":168,"cy":98,"r":99,"fill":100},"690",[69,170,106],{"x":171,"y":104,"style":172,"fill":74,"textAnchor":75},"650","text-anchor:middle;font-size:16px;font-weight:bold;font-family:sans-serif;text-shadow:2px 3px 3px #59645f",[69,174,28],{"x":171,"y":109,"style":110,"fill":111,"textAnchor":75},[176,177,179],"h2",{"id":178},"prerequisites","Prerequisites",[181,182,183,191,198],"ul",{},[184,185,186,190],"li",{},[187,188,189],"strong",{},"QGIS 3.40 LTR"," or newer, or the QGIS 4 series.",[184,192,193,194,197],{},"A vector layer with labels you want to improve. The basics of switching labels on and choosing a field are in the ",[39,195,196],{"href":41},"labeling guide",".",[184,199,200],{},"The fonts you intend to use installed on every machine that renders the map, including servers.",[176,202,204],{"id":203},"start-from-a-text-format","Start from a text format",[14,206,207,208,210],{},"A ",[31,209,33],{}," holds font, size, colour and the three effect objects. Build it once, attach it to label settings, and enable labels on the layer.",[212,213,218],"pre",{"className":214,"code":215,"language":216,"meta":217,"style":217},"language-python shiki shiki-themes github-dark","from qgis.PyQt.QtGui import QColor, QFont\nfrom qgis.core import (\n    QgsProject, QgsTextFormat, QgsPalLayerSettings, QgsVectorLayerSimpleLabeling,\n    Qgis,\n)\n\nvillages = QgsProject.instance().mapLayersByName(\"settlements\")[0]\n\nfmt = QgsTextFormat()\nfont = QFont(\"Source Sans 3\")\nfont.setWeight(QFont.Weight.DemiBold)\nfmt.setFont(font)\nfmt.setSize(9.5)\nfmt.setSizeUnit(Qgis.RenderUnit.Points)\nfmt.setColor(QColor(\"#1f2a24\"))\n\nsettings = QgsPalLayerSettings()\nsettings.fieldName = \"name\"\nsettings.setFormat(fmt)\n\nvillages.setLabeling(QgsVectorLayerSimpleLabeling(settings))\nvillages.setLabelsEnabled(True)\nvillages.triggerRepaint()\n","python","",[31,219,220,239,252,258,264,270,277,302,307,318,334,340,346,357,363,375,380,391,402,408,413,419,430],{"__ignoreMap":217},[221,222,225,229,233,236],"span",{"class":223,"line":224},"line",1,[221,226,228],{"class":227},"snl16","from",[221,230,232],{"class":231},"s95oV"," qgis.PyQt.QtGui ",[221,234,235],{"class":227},"import",[221,237,238],{"class":231}," QColor, QFont\n",[221,240,242,244,247,249],{"class":223,"line":241},2,[221,243,228],{"class":227},[221,245,246],{"class":231}," qgis.core ",[221,248,235],{"class":227},[221,250,251],{"class":231}," (\n",[221,253,255],{"class":223,"line":254},3,[221,256,257],{"class":231},"    QgsProject, QgsTextFormat, QgsPalLayerSettings, QgsVectorLayerSimpleLabeling,\n",[221,259,261],{"class":223,"line":260},4,[221,262,263],{"class":231},"    Qgis,\n",[221,265,267],{"class":223,"line":266},5,[221,268,269],{"class":231},")\n",[221,271,273],{"class":223,"line":272},6,[221,274,276],{"emptyLinePlaceholder":275},true,"\n",[221,278,280,283,286,289,293,296,299],{"class":223,"line":279},7,[221,281,282],{"class":231},"villages ",[221,284,285],{"class":227},"=",[221,287,288],{"class":231}," QgsProject.instance().mapLayersByName(",[221,290,292],{"class":291},"sU2Wk","\"settlements\"",[221,294,295],{"class":231},")[",[221,297,64],{"class":298},"sDLfK",[221,300,301],{"class":231},"]\n",[221,303,305],{"class":223,"line":304},8,[221,306,276],{"emptyLinePlaceholder":275},[221,308,310,313,315],{"class":223,"line":309},9,[221,311,312],{"class":231},"fmt ",[221,314,285],{"class":227},[221,316,317],{"class":231}," QgsTextFormat()\n",[221,319,321,324,326,329,332],{"class":223,"line":320},10,[221,322,323],{"class":231},"font ",[221,325,285],{"class":227},[221,327,328],{"class":231}," QFont(",[221,330,331],{"class":291},"\"Source Sans 3\"",[221,333,269],{"class":231},[221,335,337],{"class":223,"line":336},11,[221,338,339],{"class":231},"font.setWeight(QFont.Weight.DemiBold)\n",[221,341,343],{"class":223,"line":342},12,[221,344,345],{"class":231},"fmt.setFont(font)\n",[221,347,349,352,355],{"class":223,"line":348},13,[221,350,351],{"class":231},"fmt.setSize(",[221,353,354],{"class":298},"9.5",[221,356,269],{"class":231},[221,358,360],{"class":223,"line":359},14,[221,361,362],{"class":231},"fmt.setSizeUnit(Qgis.RenderUnit.Points)\n",[221,364,366,369,372],{"class":223,"line":365},15,[221,367,368],{"class":231},"fmt.setColor(QColor(",[221,370,371],{"class":291},"\"#1f2a24\"",[221,373,374],{"class":231},"))\n",[221,376,378],{"class":223,"line":377},16,[221,379,276],{"emptyLinePlaceholder":275},[221,381,383,386,388],{"class":223,"line":382},17,[221,384,385],{"class":231},"settings ",[221,387,285],{"class":227},[221,389,390],{"class":231}," QgsPalLayerSettings()\n",[221,392,394,397,399],{"class":223,"line":393},18,[221,395,396],{"class":231},"settings.fieldName ",[221,398,285],{"class":227},[221,400,401],{"class":291}," \"name\"\n",[221,403,405],{"class":223,"line":404},19,[221,406,407],{"class":231},"settings.setFormat(fmt)\n",[221,409,411],{"class":223,"line":410},20,[221,412,276],{"emptyLinePlaceholder":275},[221,414,416],{"class":223,"line":415},21,[221,417,418],{"class":231},"villages.setLabeling(QgsVectorLayerSimpleLabeling(settings))\n",[221,420,422,425,428],{"class":223,"line":421},22,[221,423,424],{"class":231},"villages.setLabelsEnabled(",[221,426,427],{"class":298},"True",[221,429,269],{"class":231},[221,431,433],{"class":223,"line":432},23,[221,434,435],{"class":231},"villages.triggerRepaint()\n",[14,437,438,441,442,445,446,449],{},[187,439,440],{},"Breakdown:"," Setting size in points keeps text the same physical size on screen and in print, independent of map scale; map units make labels grow and shrink as you zoom, which is occasionally what you want for area names and rarely for anything else. The font weight uses Qt's scoped enum so the code works on the QGIS 4 series. Everything that follows modifies ",[31,443,444],{},"fmt"," and calls ",[31,447,448],{},"settings.setFormat(fmt)"," again, because label settings store a copy of the format rather than a reference.",[176,451,453],{"id":452},"buffers-the-default-fix","Buffers: the default fix",[14,455,456],{},"A buffer draws a halo around each glyph. A thin, light buffer under dark text is the most effective and least intrusive readability fix there is, and it should be the first thing you try.",[212,458,460],{"className":214,"code":459,"language":216,"meta":217,"style":217},"from qgis.PyQt.QtCore import Qt\nfrom qgis.core import QgsTextBufferSettings\n\nbuffer = QgsTextBufferSettings()\nbuffer.setEnabled(True)\nbuffer.setSize(0.8)\nbuffer.setSizeUnit(Qgis.RenderUnit.Millimeters)\nbuffer.setColor(QColor(\"#fbf8f0\"))\nbuffer.setOpacity(0.85)\nbuffer.setJoinStyle(Qt.PenJoinStyle.RoundJoin)\nbuffer.setFillBufferInterior(True)\n\nfmt.setBuffer(buffer)\nsettings.setFormat(fmt)\nvillages.setLabeling(QgsVectorLayerSimpleLabeling(settings))\nvillages.triggerRepaint()\n",[31,461,462,474,485,489,499,508,518,523,533,543,548,557,561,566,570,574],{"__ignoreMap":217},[221,463,464,466,469,471],{"class":223,"line":224},[221,465,228],{"class":227},[221,467,468],{"class":231}," qgis.PyQt.QtCore ",[221,470,235],{"class":227},[221,472,473],{"class":231}," Qt\n",[221,475,476,478,480,482],{"class":223,"line":241},[221,477,228],{"class":227},[221,479,246],{"class":231},[221,481,235],{"class":227},[221,483,484],{"class":231}," QgsTextBufferSettings\n",[221,486,487],{"class":223,"line":254},[221,488,276],{"emptyLinePlaceholder":275},[221,490,491,494,496],{"class":223,"line":260},[221,492,493],{"class":231},"buffer ",[221,495,285],{"class":227},[221,497,498],{"class":231}," QgsTextBufferSettings()\n",[221,500,501,504,506],{"class":223,"line":266},[221,502,503],{"class":231},"buffer.setEnabled(",[221,505,427],{"class":298},[221,507,269],{"class":231},[221,509,510,513,516],{"class":223,"line":272},[221,511,512],{"class":231},"buffer.setSize(",[221,514,515],{"class":298},"0.8",[221,517,269],{"class":231},[221,519,520],{"class":223,"line":279},[221,521,522],{"class":231},"buffer.setSizeUnit(Qgis.RenderUnit.Millimeters)\n",[221,524,525,528,531],{"class":223,"line":304},[221,526,527],{"class":231},"buffer.setColor(QColor(",[221,529,530],{"class":291},"\"#fbf8f0\"",[221,532,374],{"class":231},[221,534,535,538,541],{"class":223,"line":309},[221,536,537],{"class":231},"buffer.setOpacity(",[221,539,540],{"class":298},"0.85",[221,542,269],{"class":231},[221,544,545],{"class":223,"line":320},[221,546,547],{"class":231},"buffer.setJoinStyle(Qt.PenJoinStyle.RoundJoin)\n",[221,549,550,553,555],{"class":223,"line":336},[221,551,552],{"class":231},"buffer.setFillBufferInterior(",[221,554,427],{"class":298},[221,556,269],{"class":231},[221,558,559],{"class":223,"line":342},[221,560,276],{"emptyLinePlaceholder":275},[221,562,563],{"class":223,"line":348},[221,564,565],{"class":231},"fmt.setBuffer(buffer)\n",[221,567,568],{"class":223,"line":359},[221,569,407],{"class":231},[221,571,572],{"class":223,"line":365},[221,573,418],{"class":231},[221,575,576],{"class":223,"line":377},[221,577,435],{"class":231},[14,579,580,582,583,586,587,590,591,594],{},[187,581,440],{}," A buffer of 0.6–1 mm is enough over most imagery; wider buffers start to look like a background and obscure the map around the label. Slightly reducing opacity lets the terrain show through the halo, which reads as more refined than a solid white outline. Round joins avoid spiky corners on letters like ",[31,584,585],{},"M"," and ",[31,588,589],{},"W",". ",[31,592,593],{},"setFillBufferInterior"," fills the inside of letters so a semi-transparent text colour does not show the buffer through it. A dark buffer under light text is the inverse treatment for dark basemaps and night-mode maps. Whichever you choose, match the buffer colour to the dominant tone of the basemap rather than using pure white or black: a buffer tinted towards the map's paper colour disappears into the design, while a stark white halo draws attention to itself on every label.",[14,596,597],{},[47,598,601,604,607,610,613,621,626,629,633,637,640,645,647,650,653,656,659,664,667,670,673,676],{"viewBox":599,"role":50,"ariaLabel":600,"xmlns":52},"0 0 760 256","Choosing between buffer, background and shadow by map context: buffers for readability over variable backgrounds with minimal visual weight, backgrounds for emphasis such as road shields and callouts, shadows for light text on imagery and a raised look",[54,602,603],{},"Which effect for which job",[58,605,606],{},"Three columns. Buffer: the default, minimal weight, keeps the map visible, use for place names over imagery and hillshade. Background: strong emphasis, hides what is beneath, use for road shields, point-of-interest callouts and legend-like labels. Shadow: subtle lift, works with light text on dark imagery, use sparingly and combine with a buffer when contrast is poor.",[62,608],{"x":64,"y":64,"width":65,"height":609,"fill":67},"256",[69,611,612],{"x":71,"y":148,"style":73,"fill":74,"textAnchor":75},"Pick the lightest effect that works",[62,614],{"x":82,"y":615,"width":616,"height":617,"rx":86,"fill":618,"stroke":619,"style":620},"44","222","192","#e8efe6","#15803d","stroke-width:2.5",[69,622,20],{"x":623,"y":91,"style":624,"fill":625,"textAnchor":75},"135","text-anchor:middle;font-size:12px;font-weight:bold;font-family:sans-serif","#166534",[69,627,628],{"x":623,"y":147,"style":110,"fill":111,"textAnchor":75},"minimal weight",[69,630,632],{"x":623,"y":631,"style":110,"fill":111,"textAnchor":75},"124","map stays visible",[69,634,636],{"x":623,"y":98,"style":635,"fill":150,"textAnchor":75},"text-anchor:middle;font-size:10px;font-family:sans-serif","place names, streets",[69,638,639],{"x":623,"y":85,"style":635,"fill":150,"textAnchor":75},"over imagery",[62,641],{"x":642,"y":615,"width":616,"height":617,"rx":86,"fill":643,"stroke":644,"style":620},"269","#eff3ff","#2563eb",[69,646,24],{"x":71,"y":91,"style":624,"fill":644,"textAnchor":75},[69,648,649],{"x":71,"y":147,"style":110,"fill":111,"textAnchor":75},"strong emphasis",[69,651,652],{"x":71,"y":631,"style":110,"fill":111,"textAnchor":75},"hides the map beneath",[69,654,655],{"x":71,"y":98,"style":635,"fill":150,"textAnchor":75},"road shields, POI",[69,657,658],{"x":71,"y":85,"style":635,"fill":150,"textAnchor":75},"callouts",[62,660],{"x":661,"y":615,"width":616,"height":617,"rx":86,"fill":662,"stroke":663,"style":620},"514","#fdf2e2","#b45309",[69,665,28],{"x":666,"y":91,"style":624,"fill":663,"textAnchor":75},"625",[69,668,669],{"x":666,"y":147,"style":110,"fill":111,"textAnchor":75},"subtle lift",[69,671,672],{"x":666,"y":631,"style":110,"fill":111,"textAnchor":75},"light text on dark",[69,674,675],{"x":666,"y":98,"style":635,"fill":150,"textAnchor":75},"titles over imagery,",[69,677,678],{"x":666,"y":85,"style":635,"fill":150,"textAnchor":75},"use sparingly",[176,680,682],{"id":681},"backgrounds-boxes-shields-and-markers","Backgrounds: boxes, shields and markers",[14,684,685],{},"A background draws a shape behind the text — a rectangle, rounded rectangle, circle, ellipse, an SVG such as a road shield, or any marker symbol. It hides what is beneath, so it suits labels that should dominate: route numbers, points of interest, map annotations.",[212,687,689],{"className":214,"code":688,"language":216,"meta":217,"style":217},"from qgis.PyQt.QtCore import QSizeF, Qt\nfrom qgis.core import QgsTextBackgroundSettings\n\nroads = QgsProject.instance().mapLayersByName(\"major_roads\")[0]\n\nshield_fmt = QgsTextFormat()\nshield_fmt.setFont(QFont(\"Source Sans 3\"))\nshield_fmt.setSize(8)\nshield_fmt.setColor(QColor(\"#fffdf7\"))\n\nbackground = QgsTextBackgroundSettings()\nbackground.setEnabled(True)\nbackground.setType(QgsTextBackgroundSettings.ShapeType.ShapeRectangle)\nbackground.setSizeType(QgsTextBackgroundSettings.SizeType.SizeBuffer)\nbackground.setSize(QSizeF(1.2, 0.6))\nbackground.setSizeUnit(Qgis.RenderUnit.Millimeters)\nbackground.setRadii(QSizeF(0.8, 0.8))\nbackground.setFillColor(QColor(\"#15803d\"))\nbackground.setStrokeColor(QColor(\"#fffdf7\"))\nbackground.setStrokeWidth(0.3)\nshield_fmt.setBackground(background)\n\nshield = QgsPalLayerSettings()\nshield.fieldName = \"ref\"\nshield.placement = Qgis.LabelPlacement.Horizontal\nshield.setFormat(shield_fmt)\nroads.setLabeling(QgsVectorLayerSimpleLabeling(shield))\nroads.setLabelsEnabled(True)\nroads.triggerRepaint()\n",[31,690,691,702,713,717,735,739,748,757,767,777,781,791,800,805,810,826,831,844,854,863,873,878,882,891,902,913,919,925,935],{"__ignoreMap":217},[221,692,693,695,697,699],{"class":223,"line":224},[221,694,228],{"class":227},[221,696,468],{"class":231},[221,698,235],{"class":227},[221,700,701],{"class":231}," QSizeF, Qt\n",[221,703,704,706,708,710],{"class":223,"line":241},[221,705,228],{"class":227},[221,707,246],{"class":231},[221,709,235],{"class":227},[221,711,712],{"class":231}," QgsTextBackgroundSettings\n",[221,714,715],{"class":223,"line":254},[221,716,276],{"emptyLinePlaceholder":275},[221,718,719,722,724,726,729,731,733],{"class":223,"line":260},[221,720,721],{"class":231},"roads ",[221,723,285],{"class":227},[221,725,288],{"class":231},[221,727,728],{"class":291},"\"major_roads\"",[221,730,295],{"class":231},[221,732,64],{"class":298},[221,734,301],{"class":231},[221,736,737],{"class":223,"line":266},[221,738,276],{"emptyLinePlaceholder":275},[221,740,741,744,746],{"class":223,"line":272},[221,742,743],{"class":231},"shield_fmt ",[221,745,285],{"class":227},[221,747,317],{"class":231},[221,749,750,753,755],{"class":223,"line":279},[221,751,752],{"class":231},"shield_fmt.setFont(QFont(",[221,754,331],{"class":291},[221,756,374],{"class":231},[221,758,759,762,765],{"class":223,"line":304},[221,760,761],{"class":231},"shield_fmt.setSize(",[221,763,764],{"class":298},"8",[221,766,269],{"class":231},[221,768,769,772,775],{"class":223,"line":309},[221,770,771],{"class":231},"shield_fmt.setColor(QColor(",[221,773,774],{"class":291},"\"#fffdf7\"",[221,776,374],{"class":231},[221,778,779],{"class":223,"line":320},[221,780,276],{"emptyLinePlaceholder":275},[221,782,783,786,788],{"class":223,"line":336},[221,784,785],{"class":231},"background ",[221,787,285],{"class":227},[221,789,790],{"class":231}," QgsTextBackgroundSettings()\n",[221,792,793,796,798],{"class":223,"line":342},[221,794,795],{"class":231},"background.setEnabled(",[221,797,427],{"class":298},[221,799,269],{"class":231},[221,801,802],{"class":223,"line":348},[221,803,804],{"class":231},"background.setType(QgsTextBackgroundSettings.ShapeType.ShapeRectangle)\n",[221,806,807],{"class":223,"line":359},[221,808,809],{"class":231},"background.setSizeType(QgsTextBackgroundSettings.SizeType.SizeBuffer)\n",[221,811,812,815,818,821,824],{"class":223,"line":365},[221,813,814],{"class":231},"background.setSize(QSizeF(",[221,816,817],{"class":298},"1.2",[221,819,820],{"class":231},", ",[221,822,823],{"class":298},"0.6",[221,825,374],{"class":231},[221,827,828],{"class":223,"line":377},[221,829,830],{"class":231},"background.setSizeUnit(Qgis.RenderUnit.Millimeters)\n",[221,832,833,836,838,840,842],{"class":223,"line":382},[221,834,835],{"class":231},"background.setRadii(QSizeF(",[221,837,515],{"class":298},[221,839,820],{"class":231},[221,841,515],{"class":298},[221,843,374],{"class":231},[221,845,846,849,852],{"class":223,"line":393},[221,847,848],{"class":231},"background.setFillColor(QColor(",[221,850,851],{"class":291},"\"#15803d\"",[221,853,374],{"class":231},[221,855,856,859,861],{"class":223,"line":404},[221,857,858],{"class":231},"background.setStrokeColor(QColor(",[221,860,774],{"class":291},[221,862,374],{"class":231},[221,864,865,868,871],{"class":223,"line":410},[221,866,867],{"class":231},"background.setStrokeWidth(",[221,869,870],{"class":298},"0.3",[221,872,269],{"class":231},[221,874,875],{"class":223,"line":415},[221,876,877],{"class":231},"shield_fmt.setBackground(background)\n",[221,879,880],{"class":223,"line":421},[221,881,276],{"emptyLinePlaceholder":275},[221,883,884,887,889],{"class":223,"line":432},[221,885,886],{"class":231},"shield ",[221,888,285],{"class":227},[221,890,390],{"class":231},[221,892,894,897,899],{"class":223,"line":893},24,[221,895,896],{"class":231},"shield.fieldName ",[221,898,285],{"class":227},[221,900,901],{"class":291}," \"ref\"\n",[221,903,905,908,910],{"class":223,"line":904},25,[221,906,907],{"class":231},"shield.placement ",[221,909,285],{"class":227},[221,911,912],{"class":231}," Qgis.LabelPlacement.Horizontal\n",[221,914,916],{"class":223,"line":915},26,[221,917,918],{"class":231},"shield.setFormat(shield_fmt)\n",[221,920,922],{"class":223,"line":921},27,[221,923,924],{"class":231},"roads.setLabeling(QgsVectorLayerSimpleLabeling(shield))\n",[221,926,928,931,933],{"class":223,"line":927},28,[221,929,930],{"class":231},"roads.setLabelsEnabled(",[221,932,427],{"class":298},[221,934,269],{"class":231},[221,936,938],{"class":223,"line":937},29,[221,939,940],{"class":231},"roads.triggerRepaint()\n",[14,942,943,945,946,949,950,953,954,957,958,961,962,197],{},[187,944,440],{}," ",[31,947,948],{},"SizeBuffer"," sizes the shape to the text plus the given padding, so the box grows with longer route numbers; ",[31,951,952],{},"SizeFixed"," uses an absolute size, which suits circular symbols of constant diameter. Radii round the corners. A thin light stroke separates the shield from dark roads beneath. Horizontal placement keeps shields upright rather than following the line, matching how road atlases draw them. For a real shield graphic, set the type to ",[31,955,956],{},"ShapeSVG"," and point ",[31,959,960],{},"setSvgFile"," at an SVG with parameterised fill so the colour can still be set from code, the same mechanism as ",[39,963,965],{"href":964},"\u002Fpyqgis-cartography-visualization\u002Fsymbol-layers-and-advanced-symbology\u002Fuse-svg-marker-symbol-pyqgis\u002F","SVG marker symbols",[176,967,969],{"id":968},"shadows-and-data-defined-colours","Shadows and data-defined colours",[14,971,972],{},"A shadow offsets a blurred copy of the text or its background. It gives light text a lift over dark imagery and adds depth to backgrounds; used on every label it makes a map look dated.",[212,974,976],{"className":214,"code":975,"language":216,"meta":217,"style":217},"from qgis.core import QgsTextShadowSettings, QgsPalLayerSettings, QgsProperty\n\ntitle_fmt = QgsTextFormat(fmt)\ntitle_fmt.setColor(QColor(\"#fffdf7\"))\ntitle_fmt.setSize(12)\n\nshadow = QgsTextShadowSettings()\nshadow.setEnabled(True)\nshadow.setShadowPlacement(QgsTextShadowSettings.ShadowPlacement.ShadowLowest)\nshadow.setOffsetAngle(135)\nshadow.setOffsetDistance(0.5)\nshadow.setOffsetUnit(Qgis.RenderUnit.Millimeters)\nshadow.setBlurRadius(1.5)\nshadow.setColor(QColor(\"#17211d\"))\nshadow.setOpacity(0.7)\ntitle_fmt.setShadow(shadow)\n\ntowns = QgsPalLayerSettings(settings)\ntowns.setFormat(title_fmt)\nprops = towns.dataDefinedProperties()\nprops.setProperty(QgsPalLayerSettings.Property.Color, QgsProperty.fromExpression(\n    \"CASE WHEN \\\"status\\\" = 'city' THEN '#fffdf7' ELSE '#e8efe6' END\"))\nprops.setProperty(QgsPalLayerSettings.Property.Size, QgsProperty.fromExpression(\n    \"CASE WHEN \\\"population\\\" > 100000 THEN 13 ELSE 10 END\"))\ntowns.setDataDefinedProperties(props)\n",[31,977,978,989,993,1003,1012,1022,1026,1036,1045,1050,1059,1069,1074,1084,1094,1104,1109,1113,1123,1128,1138,1143,1161,1166,1182],{"__ignoreMap":217},[221,979,980,982,984,986],{"class":223,"line":224},[221,981,228],{"class":227},[221,983,246],{"class":231},[221,985,235],{"class":227},[221,987,988],{"class":231}," QgsTextShadowSettings, QgsPalLayerSettings, QgsProperty\n",[221,990,991],{"class":223,"line":241},[221,992,276],{"emptyLinePlaceholder":275},[221,994,995,998,1000],{"class":223,"line":254},[221,996,997],{"class":231},"title_fmt ",[221,999,285],{"class":227},[221,1001,1002],{"class":231}," QgsTextFormat(fmt)\n",[221,1004,1005,1008,1010],{"class":223,"line":260},[221,1006,1007],{"class":231},"title_fmt.setColor(QColor(",[221,1009,774],{"class":291},[221,1011,374],{"class":231},[221,1013,1014,1017,1020],{"class":223,"line":266},[221,1015,1016],{"class":231},"title_fmt.setSize(",[221,1018,1019],{"class":298},"12",[221,1021,269],{"class":231},[221,1023,1024],{"class":223,"line":272},[221,1025,276],{"emptyLinePlaceholder":275},[221,1027,1028,1031,1033],{"class":223,"line":279},[221,1029,1030],{"class":231},"shadow ",[221,1032,285],{"class":227},[221,1034,1035],{"class":231}," QgsTextShadowSettings()\n",[221,1037,1038,1041,1043],{"class":223,"line":304},[221,1039,1040],{"class":231},"shadow.setEnabled(",[221,1042,427],{"class":298},[221,1044,269],{"class":231},[221,1046,1047],{"class":223,"line":309},[221,1048,1049],{"class":231},"shadow.setShadowPlacement(QgsTextShadowSettings.ShadowPlacement.ShadowLowest)\n",[221,1051,1052,1055,1057],{"class":223,"line":320},[221,1053,1054],{"class":231},"shadow.setOffsetAngle(",[221,1056,623],{"class":298},[221,1058,269],{"class":231},[221,1060,1061,1064,1067],{"class":223,"line":336},[221,1062,1063],{"class":231},"shadow.setOffsetDistance(",[221,1065,1066],{"class":298},"0.5",[221,1068,269],{"class":231},[221,1070,1071],{"class":223,"line":342},[221,1072,1073],{"class":231},"shadow.setOffsetUnit(Qgis.RenderUnit.Millimeters)\n",[221,1075,1076,1079,1082],{"class":223,"line":348},[221,1077,1078],{"class":231},"shadow.setBlurRadius(",[221,1080,1081],{"class":298},"1.5",[221,1083,269],{"class":231},[221,1085,1086,1089,1092],{"class":223,"line":359},[221,1087,1088],{"class":231},"shadow.setColor(QColor(",[221,1090,1091],{"class":291},"\"#17211d\"",[221,1093,374],{"class":231},[221,1095,1096,1099,1102],{"class":223,"line":365},[221,1097,1098],{"class":231},"shadow.setOpacity(",[221,1100,1101],{"class":298},"0.7",[221,1103,269],{"class":231},[221,1105,1106],{"class":223,"line":377},[221,1107,1108],{"class":231},"title_fmt.setShadow(shadow)\n",[221,1110,1111],{"class":223,"line":382},[221,1112,276],{"emptyLinePlaceholder":275},[221,1114,1115,1118,1120],{"class":223,"line":393},[221,1116,1117],{"class":231},"towns ",[221,1119,285],{"class":227},[221,1121,1122],{"class":231}," QgsPalLayerSettings(settings)\n",[221,1124,1125],{"class":223,"line":404},[221,1126,1127],{"class":231},"towns.setFormat(title_fmt)\n",[221,1129,1130,1133,1135],{"class":223,"line":410},[221,1131,1132],{"class":231},"props ",[221,1134,285],{"class":227},[221,1136,1137],{"class":231}," towns.dataDefinedProperties()\n",[221,1139,1140],{"class":223,"line":415},[221,1141,1142],{"class":231},"props.setProperty(QgsPalLayerSettings.Property.Color, QgsProperty.fromExpression(\n",[221,1144,1145,1148,1151,1154,1156,1159],{"class":223,"line":421},[221,1146,1147],{"class":291},"    \"CASE WHEN ",[221,1149,1150],{"class":298},"\\\"",[221,1152,1153],{"class":291},"status",[221,1155,1150],{"class":298},[221,1157,1158],{"class":291}," = 'city' THEN '#fffdf7' ELSE '#e8efe6' END\"",[221,1160,374],{"class":231},[221,1162,1163],{"class":223,"line":432},[221,1164,1165],{"class":231},"props.setProperty(QgsPalLayerSettings.Property.Size, QgsProperty.fromExpression(\n",[221,1167,1168,1170,1172,1175,1177,1180],{"class":223,"line":893},[221,1169,1147],{"class":291},[221,1171,1150],{"class":298},[221,1173,1174],{"class":291},"population",[221,1176,1150],{"class":298},[221,1178,1179],{"class":291}," > 100000 THEN 13 ELSE 10 END\"",[221,1181,374],{"class":231},[221,1183,1184],{"class":223,"line":904},[221,1185,1186],{"class":231},"towns.setDataDefinedProperties(props)\n",[14,1188,1189,945,1191,1194,1195,1199,1200,586,1203,1206],{},[187,1190,440],{},[31,1192,1193],{},"ShadowLowest"," casts the shadow from the lowest enabled component — the background if there is one, otherwise the buffer, otherwise the text — which is what makes a shadowed shield look raised as a unit. The offset angle is measured clockwise from north in QGIS's convention, so 135° is down and to the right, where light from the upper left would cast it. Data-defined properties override the static format per feature; colour and size are the two most useful, and the same approach drives ",[39,1196,1198],{"href":1197},"\u002Fpyqgis-fundamentals-environment-setup\u002Fworking-with-qgis-expressions\u002Fdata-defined-symbol-size-expression-pyqgis\u002F","data-defined symbol sizes",". Copy-constructing ",[31,1201,1202],{},"QgsTextFormat(fmt)",[31,1204,1205],{},"QgsPalLayerSettings(settings)"," reuses the earlier settings without mutating them.",[14,1208,1209],{},[47,1210,1213,1216,1219,1221,1236,1239,1243,1248,1252,1258,1264,1268,1272,1278,1280,1284,1290,1295,1298,1302,1305],{"viewBox":1211,"role":50,"ariaLabel":1212,"xmlns":52},"0 0 760 204","Saving a text format to the style library: a format built in code is added under a name, appears in every text format selector, and can be retrieved by name in other scripts and layouts so all labels share one definition",[54,1214,1215],{},"Define text once, use it everywhere",[58,1217,1218],{},"A text format named Settlement label with its buffer and font is added to the default style with addTextFormat. It then appears in the text format list in label properties, in layout label items and in annotations. A second script retrieves it with textFormat by name and applies it to another layer, so a change to the saved format can be rolled out consistently.",[62,1220],{"x":64,"y":64,"width":65,"height":117,"fill":67},[1222,1223,1224],"defs",{},[1225,1226,1232],"marker",{"id":1227,"viewBox":1228,"refX":764,"refY":1229,"markerWidth":1230,"markerHeight":1230,"orient":1231},"lblStyleArrow","0 0 10 10","5","7","auto-start-reverse",[1233,1234],"path",{"d":1235,"fill":111},"M0 0 L10 5 L0 10 z",[69,1237,1238],{"x":71,"y":148,"style":73,"fill":74,"textAnchor":75},"A named text format keeps a map series consistent",[62,1240],{"x":82,"y":91,"width":85,"height":1241,"rx":86,"fill":128,"stroke":150,"style":1242},"96","stroke-width:2",[69,1244,1247],{"x":631,"y":1245,"style":1246,"fill":74,"textAnchor":75},"104","text-anchor:middle;font-size:10.5px;font-weight:bold;font-family:sans-serif","format in code",[69,1249,1251],{"x":631,"y":1250,"style":635,"fill":111,"textAnchor":75},"128","font, buffer, shadow",[223,1253],{"x1":1254,"y1":1255,"x2":1256,"y2":1255,"stroke":111,"style":1257},"224","118","266","stroke-width:1.8;marker-end:url(#lblStyleArrow)",[62,1259],{"x":1260,"y":91,"width":1261,"height":1241,"rx":86,"fill":1262,"stroke":1263,"style":620},"274","210","#eef7f4","#0f766e",[69,1265,1267],{"x":1266,"y":1245,"style":1246,"fill":1263,"textAnchor":75},"379","style library",[69,1269,1271],{"x":1266,"y":1250,"style":1270,"fill":111,"textAnchor":75},"text-anchor:middle;font-size:10px;font-family:monospace","\"Settlement label\"",[223,1273],{"x1":1274,"y1":1241,"x2":1275,"y2":1276,"stroke":111,"style":1277},"484","526","72","stroke-width:1.6;marker-end:url(#lblStyleArrow)",[223,1279],{"x1":1274,"y1":1255,"x2":1275,"y2":1255,"stroke":111,"style":1277},[223,1281],{"x1":1274,"y1":1282,"x2":1275,"y2":1283,"stroke":111,"style":1277},"140","164",[62,1285],{"x":1286,"y":1287,"width":1288,"height":99,"rx":764,"fill":618,"stroke":619,"style":1289},"534","50","202","stroke-width:1.8",[69,1291,1294],{"x":1292,"y":1293,"style":110,"fill":111,"textAnchor":75},"635","75","layer labels",[62,1296],{"x":1286,"y":1297,"width":1288,"height":99,"rx":764,"fill":618,"stroke":619,"style":1289},"98",[69,1299,1301],{"x":1292,"y":1300,"style":110,"fill":111,"textAnchor":75},"123","layout label items",[62,1303],{"x":1286,"y":1304,"width":1288,"height":99,"rx":764,"fill":618,"stroke":619,"style":1289},"146",[69,1306,1308],{"x":1292,"y":1307,"style":110,"fill":111,"textAnchor":75},"171","annotations",[176,1310,1312],{"id":1311},"rich-text-and-a-reusable-format","Rich text and a reusable format",[14,1314,1315],{},"Since QGIS 3.14 a text format can interpret a subset of HTML, which lets one label mix weights, sizes and colours — a name in bold with a smaller population figure beneath it. And any finished format can be saved in the style library under a name, so layouts, annotations and other layers use the identical definition.",[212,1317,1319],{"className":214,"code":1318,"language":216,"meta":217,"style":217},"from qgis.core import QgsStyle\n\nrich = QgsTextFormat(fmt)\nrich.setAllowHtmlFormatting(True)\n\nrich_settings = QgsPalLayerSettings(settings)\nrich_settings.isExpression = True\nrich_settings.fieldName = (\n    \"'\u003Cb>' || \\\"name\\\" || '\u003C\u002Fb>\u003Cbr>'\"\n    \" || '\u003Cspan style=\\\"font-size:7pt;color:#59645f\\\">pop. '\"\n    \" || format_number(\\\"population\\\", 0) || '\u003C\u002Fspan>'\"\n)\nrich_settings.setFormat(rich)\nvillages.setLabeling(QgsVectorLayerSimpleLabeling(rich_settings))\nvillages.triggerRepaint()\n\nstyle = QgsStyle.defaultStyle()\nstyle.addTextFormat(\"Settlement label\", fmt, True)\nreused = style.textFormat(\"Settlement label\")\nprint(\"saved and retrieved:\", reused.isValid())\n",[31,1320,1321,1332,1336,1345,1354,1358,1367,1377,1386,1401,1416,1430,1434,1439,1444,1448,1452,1462,1476,1490],{"__ignoreMap":217},[221,1322,1323,1325,1327,1329],{"class":223,"line":224},[221,1324,228],{"class":227},[221,1326,246],{"class":231},[221,1328,235],{"class":227},[221,1330,1331],{"class":231}," QgsStyle\n",[221,1333,1334],{"class":223,"line":241},[221,1335,276],{"emptyLinePlaceholder":275},[221,1337,1338,1341,1343],{"class":223,"line":254},[221,1339,1340],{"class":231},"rich ",[221,1342,285],{"class":227},[221,1344,1002],{"class":231},[221,1346,1347,1350,1352],{"class":223,"line":260},[221,1348,1349],{"class":231},"rich.setAllowHtmlFormatting(",[221,1351,427],{"class":298},[221,1353,269],{"class":231},[221,1355,1356],{"class":223,"line":266},[221,1357,276],{"emptyLinePlaceholder":275},[221,1359,1360,1363,1365],{"class":223,"line":272},[221,1361,1362],{"class":231},"rich_settings ",[221,1364,285],{"class":227},[221,1366,1122],{"class":231},[221,1368,1369,1372,1374],{"class":223,"line":279},[221,1370,1371],{"class":231},"rich_settings.isExpression ",[221,1373,285],{"class":227},[221,1375,1376],{"class":298}," True\n",[221,1378,1379,1382,1384],{"class":223,"line":304},[221,1380,1381],{"class":231},"rich_settings.fieldName ",[221,1383,285],{"class":227},[221,1385,251],{"class":231},[221,1387,1388,1391,1393,1396,1398],{"class":223,"line":309},[221,1389,1390],{"class":291},"    \"'\u003Cb>' || ",[221,1392,1150],{"class":298},[221,1394,1395],{"class":291},"name",[221,1397,1150],{"class":298},[221,1399,1400],{"class":291}," || '\u003C\u002Fb>\u003Cbr>'\"\n",[221,1402,1403,1406,1408,1411,1413],{"class":223,"line":320},[221,1404,1405],{"class":291},"    \" || '\u003Cspan style=",[221,1407,1150],{"class":298},[221,1409,1410],{"class":291},"font-size:7pt;color:#59645f",[221,1412,1150],{"class":298},[221,1414,1415],{"class":291},">pop. '\"\n",[221,1417,1418,1421,1423,1425,1427],{"class":223,"line":336},[221,1419,1420],{"class":291},"    \" || format_number(",[221,1422,1150],{"class":298},[221,1424,1174],{"class":291},[221,1426,1150],{"class":298},[221,1428,1429],{"class":291},", 0) || '\u003C\u002Fspan>'\"\n",[221,1431,1432],{"class":223,"line":342},[221,1433,269],{"class":231},[221,1435,1436],{"class":223,"line":348},[221,1437,1438],{"class":231},"rich_settings.setFormat(rich)\n",[221,1440,1441],{"class":223,"line":359},[221,1442,1443],{"class":231},"villages.setLabeling(QgsVectorLayerSimpleLabeling(rich_settings))\n",[221,1445,1446],{"class":223,"line":365},[221,1447,435],{"class":231},[221,1449,1450],{"class":223,"line":377},[221,1451,276],{"emptyLinePlaceholder":275},[221,1453,1454,1457,1459],{"class":223,"line":382},[221,1455,1456],{"class":231},"style ",[221,1458,285],{"class":227},[221,1460,1461],{"class":231}," QgsStyle.defaultStyle()\n",[221,1463,1464,1467,1469,1472,1474],{"class":223,"line":393},[221,1465,1466],{"class":231},"style.addTextFormat(",[221,1468,1271],{"class":291},[221,1470,1471],{"class":231},", fmt, ",[221,1473,427],{"class":298},[221,1475,269],{"class":231},[221,1477,1478,1481,1483,1486,1488],{"class":223,"line":404},[221,1479,1480],{"class":231},"reused ",[221,1482,285],{"class":227},[221,1484,1485],{"class":231}," style.textFormat(",[221,1487,1271],{"class":291},[221,1489,269],{"class":231},[221,1491,1492,1495,1498,1501],{"class":223,"line":410},[221,1493,1494],{"class":298},"print",[221,1496,1497],{"class":231},"(",[221,1499,1500],{"class":291},"\"saved and retrieved:\"",[221,1502,1503],{"class":231},", reused.isValid())\n",[14,1505,1506,1508,1509,1512,1513,1516,1517,1520,1521,1524,1525,1527,1528,1531,1532,197],{},[187,1507,440],{}," HTML labels are built with an expression that concatenates tags around field values; ",[31,1510,1511],{},"isExpression"," tells the label engine the field name is an expression. Supported markup includes bold, italic, colour, font size and line breaks — enough for most two-line labels, not a web page. Escape any field values that could contain ",[31,1514,1515],{},"\u003C"," or ",[31,1518,1519],{},"&",", or the label renders as broken markup. ",[31,1522,1523],{},"addTextFormat"," with ",[31,1526,427],{}," saves immediately to the user's style database; ",[31,1529,1530],{},"textFormat"," retrieves by name. The style library works the same way for symbols and colour ramps, as covered in ",[39,1533,1535],{"href":1534},"\u002Fpyqgis-cartography-visualization\u002Fprogrammatic-layer-styling\u002Fuse-style-manager-and-symbol-library-pyqgis\u002F","using the style manager and symbol library",[176,1537,1539],{"id":1538},"qgis-version-compatibility","QGIS version compatibility",[14,1541,1542,820,1544,820,1547,586,1550,1553,1554,1557,1558,1561,1562,1557,1565,1568,1569,1572],{},[31,1543,33],{},[31,1545,1546],{},"QgsTextBufferSettings",[31,1548,1549],{},"QgsTextBackgroundSettings",[31,1551,1552],{},"QgsTextShadowSettings"," have been stable since QGIS 3.0. HTML formatting arrived in 3.14 and grew more CSS support in later releases. ",[31,1555,1556],{},"Qgis.RenderUnit"," replaced ",[31,1559,1560],{},"QgsUnitTypes.RenderMillimeters"," in 3.30, ",[31,1563,1564],{},"Qgis.LabelPlacement",[31,1566,1567],{},"QgsPalLayerSettings.Horizontal"," in 3.26, and ",[31,1570,1571],{},"QgsPalLayerSettings.Property.Color"," is the scoped form of the data-defined keys; the QGIS 4 series accepts only the scoped names.",[176,1574,1576],{"id":1575},"troubleshooting","Troubleshooting",[181,1578,1579,1588,1594,1603,1612],{},[184,1580,1581,945,1584,1587],{},[187,1582,1583],{},"Changes do not appear.",[31,1585,1586],{},"setFormat"," was not called again after modifying the format, or the layer was not repainted.",[184,1589,1590,1593],{},[187,1591,1592],{},"Buffers look jagged."," Join style is miter; use round joins.",[184,1595,1596,1599,1600,1602],{},[187,1597,1598],{},"The background shape is tiny."," Size type is fixed with a zero size; use ",[31,1601,948],{}," with padding.",[184,1604,1605,945,1608,1611],{},[187,1606,1607],{},"HTML tags show as text.",[31,1609,1610],{},"setAllowHtmlFormatting(True)"," is missing.",[184,1613,1614,1617],{},[187,1615,1616],{},"Fonts differ on the server."," The font is not installed there; QGIS substitutes silently.",[176,1619,1621],{"id":1620},"conclusion","Conclusion",[14,1623,1624],{},"Start every label with a text format in point units, reach for a thin light buffer first, use backgrounds where a label should dominate and shadows sparingly for light text on dark imagery. Drive colour and size from data where categories matter, use HTML for mixed two-line labels, and save the finished format to the style library so every map in a series shares the same typography.",[176,1626,1628],{"id":1627},"frequently-asked-questions","Frequently Asked Questions",[14,1630,1631,1634,1635,1638],{},[187,1632,1633],{},"Can a buffer use a blend mode?","\nYes. ",[31,1636,1637],{},"setBlendMode"," on the buffer settings, for example multiply over light basemaps, softens the halo into the map.",[14,1640,1641,1644,1645,1648,1649,1652],{},[187,1642,1643],{},"How do I apply one format to layout labels too?","\nRetrieve the saved format with ",[31,1646,1647],{},"QgsStyle.defaultStyle().textFormat(name)"," and call ",[31,1650,1651],{},"setTextFormat"," on the layout label item.",[14,1654,1655,1658],{},[187,1656,1657],{},"Why do labels overlap despite buffers?","\nBuffers do not affect collision detection much; adjust placement and priority settings instead.",[14,1660,1661,1664],{},[187,1662,1663],{},"Do these effects slow rendering?","\nBlurred shadows are the most expensive. On maps with thousands of labels, prefer buffers.",[176,1666,1668],{"id":1667},"related","Related",[181,1670,1671,1676,1682,1688,1694],{},[184,1672,1673,1675],{},[39,1674,42],{"href":41}," — the guide this recipe belongs to",[184,1677,1678],{},[39,1679,1681],{"href":1680},"\u002Fpyqgis-cartography-visualization\u002Flabeling-and-annotations\u002Fadd-rule-based-labels-pyqgis\u002F","Add Rule-Based Labels in PyQGIS",[184,1683,1684],{},[39,1685,1687],{"href":1686},"\u002Fpyqgis-cartography-visualization\u002Flabeling-and-annotations\u002Fcontrol-label-placement-and-collisions-pyqgis\u002F","Control Label Placement and Collisions in PyQGIS",[184,1689,1690],{},[39,1691,1693],{"href":1692},"\u002Fpyqgis-cartography-visualization\u002Flabeling-and-annotations\u002Fcurved-labels-along-lines-pyqgis\u002F","Place Curved Labels Along Lines in PyQGIS",[184,1695,1696],{},[39,1697,1698],{"href":1534},"Use the Style Manager and Symbol Library in PyQGIS",[1700,1701,1702],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":217,"searchDepth":241,"depth":241,"links":1704},[1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715],{"id":178,"depth":241,"text":179},{"id":203,"depth":241,"text":204},{"id":452,"depth":241,"text":453},{"id":681,"depth":241,"text":682},{"id":968,"depth":241,"text":969},{"id":1311,"depth":241,"text":1312},{"id":1538,"depth":241,"text":1539},{"id":1575,"depth":241,"text":1576},{"id":1620,"depth":241,"text":1621},{"id":1627,"depth":241,"text":1628},{"id":1667,"depth":241,"text":1668},"Make labels readable over busy maps with QgsTextFormat — halos with QgsTextBufferSettings, shield and callout-style backgrounds with QgsTextBackgroundSettings, drop shadows, HTML formatting, and data-defined colours — plus reusable text formats saved to the style library.","md",{"slug":1719,"type":1720,"breadcrumb":1721,"datePublished":1722,"dateModified":1722},"format-label-buffers-backgrounds-and-shadows-pyqgis","article","Label Buffers, Backgrounds and Shadows","2026-09-17","\u002Fpyqgis-cartography-visualization\u002Flabeling-and-annotations\u002Fformat-label-buffers-backgrounds-and-shadows-pyqgis",{"title":5,"description":1716},"pyqgis-cartography-visualization\u002Flabeling-and-annotations\u002Fformat-label-buffers-backgrounds-and-shadows-pyqgis\u002Findex","g0mbdViC0Uj2JtjpQ4sbhkIahu8OjogA7WE4UclIn-M",1789632906584]