[{"data":1,"prerenderedAt":2155},["ShallowReactive",2],{"blog-pt-bootstrap-grid-thinking-for-pdf":3},{"id":4,"title":5,"author":6,"body":10,"date":2141,"description":2142,"draft":2143,"extension":2144,"howTo":2145,"image":2145,"meta":2146,"navigation":912,"path":2147,"seo":2148,"stem":2149,"tags":2150,"updated":2145,"__hash__":2154},"blogPt/pt/blog/017.bootstrap-grid-thinking-for-pdf.md","Pensamento Bootstrap para PDF: a grade de 12 colunas do gpdf",{"name":7,"url":8,"avatar":9},"Taiki Noda","https://nadai.dev/en/about","https://nadai.dev/og-default.png",{"type":11,"value":12,"toc":2118},"minimark",[13,18,26,34,38,50,63,70,87,91,94,118,125,128,132,135,168,179,193,196,200,203,226,229,233,238,248,272,276,279,289,293,304,308,315,326,450,453,457,464,613,638,644,648,664,668,816,838,842,865,880,888,892,895,1929,1939,1943,1946,1971,1974,1978,1988,2006,2016,2030,2040,2044,2051,2055,2058,2075,2089,2093,2114],[14,15,17],"h2",{"id":16},"tldr","TL;DR",[19,20,21,25],"p",{},[22,23,24],"strong",{},"gpdf usa a grade de 12 colunas do Bootstrap. Doze, porque divide certinho em 1, 2, 3, 4 e 6 — as repartições que você de fato quer. Mantivemos o modelo de span inteiro e jogamos fora todo o resto: sem breakpoints, sem gutter, sem order, sem auto-fill."," Uma página é uma pilha de linhas; cada linha é um Box horizontal; as colunas dentro são larguras em doze avos.",[19,27,28,29,33],{},"É a grade inteira. A implementação tem cerca de 30 linhas de Go. O interessante é o que ",[30,31,32],"em",{},"não"," portamos.",[14,35,37],{"id":36},"por-que-este-artigo-existe","Por que este artigo existe",[19,39,40,41,45,46,49],{},"gpdf é uma biblioteca Go para gerar PDFs. A API de layout de alto nível é um builder: ",[42,43,44],"code",{},"page.AutoRow → r.Col(span, fn) → c.Text/Image/Table",". Quem encontra ",[42,47,48],{},"r.Col(4, ...)"," pela primeira vez costuma fazer três perguntas:",[51,52,53,57,60],"ol",{},[54,55,56],"li",{},"Por que 12? Por que não 16, 24 ou «quantas eu quiser»?",[54,58,59],{},"Isso é CSS Grid? Bootstrap? Outra coisa?",[54,61,62],{},"O que acontece se meus span não somarem 12?",[19,64,65,66,69],{},"Este post percorre as decisões de design por trás dessa API. Quase todas convergem para um princípio: ",[22,67,68],{},"renderização de PDF precisa ser previsível, não adaptativa."," Uma página web sofre reflow ao redimensionar. Um PDF não. Essa diferença sozinha elimina a maior parte do que torna grades web complicadas e nos permite entregar uma ideia bem menor.",[19,71,72,73,76,77,82,83,86],{},"Se você só quer saber ",[30,74,75],{},"como"," usar, a receita em ",[78,79,81],"a",{"href":80},"/pt/blog/12-column-grid","/blog/12-column-grid"," é mais direta. Este post é sobre ",[30,84,85],{},"por que"," tem essa cara.",[14,88,90],{"id":89},"três-opções-para-diagramar-um-pdf","Três opções para diagramar um PDF",[19,92,93],{},"Quando começamos a API de alto nível, as opções reais eram três:",[51,95,96,102,108],{},[54,97,98,101],{},[22,99,100],{},"Posicionamento absoluto."," «Desenhe texto em (72, 540) em pontos.» É o que a maioria das libs PDF de baixo nível em Go oferece. Poder máximo, ergonomia péssima. Você calcula cada coordenada na mão.",[54,103,104,107],{},[22,105,106],{},"Flow + flexbox."," Empilha o conteúdo de cima para baixo; linhas distribuem filhos horizontalmente com grow/shrink. Poderoso, mas a passada de layout não é trivial — precisa de um solver de restrições, e os erros de arredondamento se acumulam.",[54,109,110,113,114,117],{},[22,111,112],{},"Grade fixa + razões."," Página é pilha de linhas. Linha é dividida em N slots iguais. Cada coluna pega um número inteiro de slots. Largura = ",[42,115,116],{},"slots / N × largura_da_linha",". Sem solver. Sem grow/shrink.",[19,119,120,121,124],{},"Escolhemos a opção 3. O Bootstrap chegou ao mesmo ponto há mais de uma década pelo mesmo motivo: ",[22,122,123],{},"a maioria dos layouts que você precisa são layouts de fração inteira."," Duas colunas iguais. 1/3 + 2/3. Quatro cards na linha. Linha 25-50-25. Nada disso pede solver.",[19,126,127],{},"Restou a pergunta: quantos slots?",[14,129,131],{"id":130},"por-que-12","Por que 12",[19,133,134],{},"12 não é mágica, mas também não é arbitrário. Pense em quais divisões inteiras você de fato quer num documento:",[136,137,138,144,150,156,162],"ul",{},[54,139,140,143],{},[22,141,142],{},"2 colunas"," — metades esquerda/direita",[54,145,146,149],{},[22,147,148],{},"3 colunas"," — terços (galeria de três cards)",[54,151,152,155],{},[22,153,154],{},"4 colunas"," — quartos (faixa de KPI)",[54,157,158,161],{},[22,159,160],{},"6 colunas"," — sextos (raros, painéis laterais estreitos)",[54,163,164,167],{},[22,165,166],{},"12 colunas"," — doze avos (raros, separadores finos)",[19,169,170,171,174,175,178],{},"Olhe os divisores de 12: 1, 2, 3, 4, 6, 12. Ou seja, ",[30,172,173],{},"toda"," divisão inteira útil até um sexto. 10 não te dá terços. 16 também não. 24 dá tudo, mas dobra a carga cognitiva — você escreve ",[42,176,177],{},"r.Col(8, ...)"," e tem que lembrar se isso é um terço (24/3) ou dois terços (8/12). 12 é o menor número que cobre as repartições que as pessoas usam de verdade.",[19,180,181,182,185,186,188,189,192],{},"O Bootstrap pousou em 12 em 2011 exatamente por isso. Depois o CSS Grid subiu mais um nível e deixou você escrever ",[42,183,184],{},"1fr 2fr 1fr"," direto, eliminando o número mágico. Mas frações não saem de graça — empurram trabalho para quem lê o seu layout. ",[42,187,48],{}," é concretamente «um terço da linha». ",[42,190,191],{},"r.Col(2fr, ...)"," exige olhar todos os irmãos antes de saber o que significa.",[19,194,195],{},"Em PDFs, onde o layout é estável e a inspeção é a olho, o modelo inteiro vence.",[14,197,199],{"id":198},"o-que-mantivemos-do-bootstrap","O que mantivemos do Bootstrap",[19,201,202],{},"Três coisas, e só:",[51,204,205,211,220],{},[54,206,207,210],{},[22,208,209],{},"O doze."," O denominador. O único número no mostrador.",[54,212,213,216,217,219],{},[22,214,215],{},"Span como inteiro 1–12."," Nem fração, nem unidade CSS. ",[42,218,48],{}," reivindica quatro doze avos da linha.",[54,221,222,225],{},[22,223,224],{},"O modelo mental."," Página é pilha de linhas. Linha é dividida em colunas. A mesma forma da grade que você escreve em HTML há dez anos.",[19,227,228],{},"Até aqui igual ao Bootstrap. A parte realmente interessante vem agora.",[14,230,232],{"id":231},"o-que-jogamos-fora","O que jogamos fora",[234,235,237],"h3",{"id":236},"breakpoints","Breakpoints",[19,239,240,243,244,247],{},[42,241,242],{},"col-md-6 col-lg-4"," do Bootstrap faz uma coluna ocupar metade no tablet e um terço no desktop. Útil na web. ",[22,245,246],{},"Inútil em PDF."," A página de PDF é canvas fixo. Não há viewport para consultar, não há evento de resize, não há media query. Apagamos os breakpoints inteiros.",[19,249,250,251,254,255,254,258,254,261,254,264,267,268,271],{},"A economia é maior do que parece. Os breakpoints são a razão de frameworks CSS publicarem variantes ",[42,252,253],{},"col-xs-*",", ",[42,256,257],{},"col-sm-*",[42,259,260],{},"col-md-*",[42,262,263],{},"col-lg-*",[42,265,266],{},"col-xl-*"," — cinco cópias da mesma classe. Nenhuma delas existe no gpdf. A API é ",[42,269,270],{},"r.Col(span int, fn func(*ColBuilder))",". Uma assinatura. Um único compartimento mental.",[234,273,275],{"id":274},"gutter","Gutter",[19,277,278],{},"As linhas do Bootstrap vêm com padding horizontal entre colunas por padrão. PDFs não precisam de default, porque o espaço entre colunas depende totalmente do que se renderiza — uma tabela compacta vai com 0, uma seção hero quer 24pt de respiro, uma linha de fatura pode querer 0.5pt de separador. Decidimos deixar o espaçamento explícito.",[19,280,281,282,285,286],{},"Quer gutter? Põe: solte um ",[42,283,284],{},"c.Spacer(...)"," entre colunas, ou embrulhe o conteúdo num Box com padding. A grade nunca insere pixels que você não pediu. ",[22,287,288],{},"Sem gutter é o default certo num meio impresso onde cada ponto importa.",[234,290,292],{"id":291},"order","Order",[19,294,295,296,299,300,303],{},"CSS deixa reordenar colunas visualmente com ",[42,297,298],{},"order: 2",". Útil em design responsivo, onde o mesmo DOM gera ordem visual diferente em telas pequenas. ",[22,301,302],{},"Inútil em PDFs."," A ordem em que as colunas aparecem no arquivo é a ordem em que aparecem na página. Nem cogitamos.",[234,305,307],{"id":306},"auto-fill-auto-fit","Auto-fill / auto-fit",[19,309,310,311,314],{},"CSS Grid tem ",[42,312,313],{},"repeat(auto-fit, minmax(200px, 1fr))"," — preencha a linha com quantas colunas de pelo menos 200px couberem. Lindo para galerias web. Em PDF, você sabe a largura da página em build time. Não precisa que o motor de layout descubra.",[19,316,317,318,321,322,325],{},"Quer 4 cards numa linha? ",[42,319,320],{},"r.Col(3, ...)"," quatro vezes. 6? ",[42,323,324],{},"r.Col(2, ...)"," seis vezes. A versão «auto» é um for no seu próprio código:",[327,328,333],"pre",{"className":329,"code":330,"language":331,"meta":332,"style":332},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","for _, item := range items {\n    r.Col(3, func(c *template.ColBuilder) {\n        c.Text(item.Name)\n    })\n}\n","go","",[42,334,335,367,414,438,444],{"__ignoreMap":332},[336,337,340,344,348,352,355,358,361,364],"span",{"class":338,"line":339},"line",1,[336,341,343],{"class":342},"s7zQu","for",[336,345,347],{"class":346},"sTEyZ"," _",[336,349,351],{"class":350},"sMK4o",",",[336,353,354],{"class":346}," item ",[336,356,357],{"class":350},":=",[336,359,360],{"class":342}," range",[336,362,363],{"class":346}," items ",[336,365,366],{"class":350},"{\n",[336,368,370,373,376,380,383,387,389,392,396,399,403,405,408,411],{"class":338,"line":369},2,[336,371,372],{"class":346},"    r",[336,374,375],{"class":350},".",[336,377,379],{"class":378},"s2Zo4","Col",[336,381,382],{"class":350},"(",[336,384,386],{"class":385},"sbssI","3",[336,388,351],{"class":350},[336,390,391],{"class":350}," func(",[336,393,395],{"class":394},"sHdIc","c",[336,397,398],{"class":350}," *",[336,400,402],{"class":401},"sBMFI","template",[336,404,375],{"class":350},[336,406,407],{"class":401},"ColBuilder",[336,409,410],{"class":350},")",[336,412,413],{"class":350}," {\n",[336,415,417,420,422,425,427,430,432,435],{"class":338,"line":416},3,[336,418,419],{"class":346},"        c",[336,421,375],{"class":350},[336,423,424],{"class":378},"Text",[336,426,382],{"class":350},[336,428,429],{"class":346},"item",[336,431,375],{"class":350},[336,433,434],{"class":346},"Name",[336,436,437],{"class":350},")\n",[336,439,441],{"class":338,"line":440},4,[336,442,443],{"class":350},"    })\n",[336,445,447],{"class":338,"line":446},5,[336,448,449],{"class":350},"}\n",[19,451,452],{},"Três linhas. Não precisava entrar no framework.",[234,454,456],{"id":455},"forçar-soma-dos-spans","Forçar soma dos spans",[19,458,459,460,463],{},"Surpresa: ",[22,461,462],{},"gpdf não exige que os span de coluna somem 12."," É proposital.",[327,465,467],{"className":329,"code":466,"language":331,"meta":332,"style":332},"page.AutoRow(func(r *template.RowBuilder) {\n    r.Col(4, func(c *template.ColBuilder) { c.Text(\"Terço esq.\") })\n    r.Col(4, func(c *template.ColBuilder) { c.Text(\"Terço meio\") })\n    // soma = 8. O terço direito fica em branco.\n})\n",[42,468,469,498,553,602,608],{"__ignoreMap":332},[336,470,471,474,476,479,482,485,487,489,491,494,496],{"class":338,"line":339},[336,472,473],{"class":346},"page",[336,475,375],{"class":350},[336,477,478],{"class":378},"AutoRow",[336,480,481],{"class":350},"(func(",[336,483,484],{"class":394},"r",[336,486,398],{"class":350},[336,488,402],{"class":401},[336,490,375],{"class":350},[336,492,493],{"class":401},"RowBuilder",[336,495,410],{"class":350},[336,497,413],{"class":350},[336,499,500,502,504,506,508,511,513,515,517,519,521,523,525,527,530,533,535,537,539,542,546,548,550],{"class":338,"line":369},[336,501,372],{"class":346},[336,503,375],{"class":350},[336,505,379],{"class":378},[336,507,382],{"class":350},[336,509,510],{"class":385},"4",[336,512,351],{"class":350},[336,514,391],{"class":350},[336,516,395],{"class":394},[336,518,398],{"class":350},[336,520,402],{"class":401},[336,522,375],{"class":350},[336,524,407],{"class":401},[336,526,410],{"class":350},[336,528,529],{"class":350}," {",[336,531,532],{"class":346}," c",[336,534,375],{"class":350},[336,536,424],{"class":378},[336,538,382],{"class":350},[336,540,541],{"class":350},"\"",[336,543,545],{"class":544},"sfazB","Terço esq.",[336,547,541],{"class":350},[336,549,410],{"class":350},[336,551,552],{"class":350}," })\n",[336,554,555,557,559,561,563,565,567,569,571,573,575,577,579,581,583,585,587,589,591,593,596,598,600],{"class":338,"line":416},[336,556,372],{"class":346},[336,558,375],{"class":350},[336,560,379],{"class":378},[336,562,382],{"class":350},[336,564,510],{"class":385},[336,566,351],{"class":350},[336,568,391],{"class":350},[336,570,395],{"class":394},[336,572,398],{"class":350},[336,574,402],{"class":401},[336,576,375],{"class":350},[336,578,407],{"class":401},[336,580,410],{"class":350},[336,582,529],{"class":350},[336,584,532],{"class":346},[336,586,375],{"class":350},[336,588,424],{"class":378},[336,590,382],{"class":350},[336,592,541],{"class":350},[336,594,595],{"class":544},"Terço meio",[336,597,541],{"class":350},[336,599,410],{"class":350},[336,601,552],{"class":350},[336,603,604],{"class":338,"line":440},[336,605,607],{"class":606},"sHwdD","    // soma = 8. O terço direito fica em branco.\n",[336,609,610],{"class":338,"line":446},[336,611,612],{"class":350},"})\n",[19,614,615,616,619,620,623,624,254,627,623,630,633,634,637],{},"A lib trata cada coluna como ",[42,617,618],{},"span/12 × largura_da_linha",", ponto. Se você bota 4 + 4 numa linha, o slot direito fica vazio. Se bota 7 + 8, a segunda coluna estoura para fora da linha — também é intencional, porque às vezes você quer overflow (alinhar com uma grade de layout mais larga que a página, por exemplo). O span é clampeado em 1–12 (",[42,621,622],{},"Col(0, ...)"," vira ",[42,625,626],{},"Col(1, ...)",[42,628,629],{},"Col(99, ...)",[42,631,632],{},"Col(12, ...)",", ver ",[42,635,636],{},"gpdf/template/grid.go:120","), mas sem auto-wrap nem auto-balanceamento.",[19,639,640,641],{},"O comportamento antigo do Bootstrap «se a soma passar de 12, quebra para a próxima linha» resolvia um problema responsivo real. PDFs não têm esse problema. Trocamos por um contrato mais simples: ",[22,642,643],{},"o que você escreveu é o que sai.",[234,645,647],{"id":646},"container-fluid-no-gutters-offset-pushpull","Container, fluid, no-gutters, offset, push/pull",[19,649,650,651,254,654,254,657,660,661,663],{},"Nada disso. Não tem ",[42,652,653],{},"container-fluid",[42,655,656],{},"col-md-offset-3",[42,658,659],{},"col-md-push-2"," ou qualquer equivalente das classes utilitárias do Bootstrap. Quer empurrar uma coluna pra direita? Embrulhe: ponha um ",[42,662,320],{}," vazio antes. Oito caracteres a mais, zero conceitos novos.",[14,665,667],{"id":666},"gpdf-vs-bootstrap-vs-css-grid","gpdf vs Bootstrap vs CSS Grid",[669,670,671,690],"table",{},[672,673,674],"thead",{},[675,676,677,681,684,687],"tr",{},[678,679,680],"th",{},"Recurso",[678,682,683],{},"Bootstrap (CSS)",[678,685,686],{},"CSS Grid (CSS)",[678,688,689],{},"gpdf (Go)",[691,692,693,709,727,740,757,774,786,800],"tbody",{},[675,694,695,699,701,707],{},[696,697,698],"td",{},"Tamanho da grade",[696,700,166],{},[696,702,703,704,410],{},"Arbitrário (",[42,705,706],{},"grid-template-columns",[696,708,166],{},[675,710,711,714,717,724],{},[696,712,713],{},"Unidade",[696,715,716],{},"Nomes de classe",[696,718,719,720,723],{},"Frações (",[42,721,722],{},"fr","), px, %",[696,725,726],{},"Span inteiro 1–12",[675,728,729,731,734,737],{},[696,730,237],{},[696,732,733],{},"5 (xs/sm/md/lg/xl)",[696,735,736],{},"Via media queries",[696,738,739],{},"Nenhum",[675,741,742,745,752,755],{},[696,743,744],{},"Gutter padrão",[696,746,747,748,751],{},"Sim (",[42,749,750],{},"gx-*"," controla)",[696,753,754],{},"Não",[696,756,754],{},[675,758,759,762,767,772],{},[696,760,761],{},"Reordenação visual",[696,763,764],{},[42,765,766],{},"order-*",[696,768,769,770],{},"Propriedade ",[42,771,291],{},[696,773,754],{},[675,775,776,779,781,784],{},[696,777,778],{},"Auto-fill",[696,780,754],{},[696,782,783],{},"Sim",[696,785,754],{},[675,787,788,791,794,797],{},[696,789,790],{},"Wrap se soma > 12",[696,792,793],{},"Sim (legacy) / Não (flex)",[696,795,796],{},"N/A",[696,798,799],{},"Não (overflow permitido)",[675,801,802,805,808,811],{},[696,803,804],{},"Tamanho da implementação",[696,806,807],{},"~3.000 LoC SCSS",[696,809,810],{},"Dentro do navegador",[696,812,813],{},[22,814,815],{},"~30 LoC Go",[19,817,818,819,822,823,826,827,830,831,834,835],{},"«30 LoC» é número de verdade. Abre ",[42,820,821],{},"gpdf/template/grid.go"," e conta: uma constante (",[42,824,825],{},"gridColumns = 12","), um método de builder que clampeia inteiros, e uma passada de build que emite um ",[42,828,829],{},"Box"," por linha com direção horizontal e largura ",[42,832,833],{},"Pct(span/12*100)"," por filho. Sem passada de medição, sem algoritmo flex, sem rebalanceamento. ",[22,836,837],{},"A aritmética da largura é o algoritmo.",[14,839,841],{"id":840},"como-gpdf-renderiza-isso-por-dentro","Como gpdf renderiza isso por dentro",[19,843,844,845,848,849,852,853,856,857,860,861,864],{},"Quando você chama ",[42,846,847],{},"r.Col(4, fn)",", gpdf adiciona um ",[42,850,851],{},"colEntry{span: 4, fn: fn}"," à linha. Quando o documento é construído, cada entrada vira um ",[42,854,855],{},"document.Box"," com ",[42,858,859],{},"Width: document.Pct(33,333…)"," e o conteúdo da coluna aninhado dentro. A linha em si é um Box com ",[42,862,863],{},"Direction: DirectionHorizontal",". O PDF Writer (Layer 1) percorre os Box em ordem do documento e emite content streams; o motor de layout (Layer 2) resolve largura e altura; a grade (Layer 3) faz a conversão inteiro→percentual.",[19,866,867,868,871,872,875,876,879],{},"A razão de isso parar em 30 linhas é que ",[22,869,870],{},"percentuais e inteiros compõem"," sem erro de arredondamento na fronteira de layout. Coluna dentro de coluna dentro de coluna ainda é só uma pilha de multiplicações ",[42,873,874],{},"Pct"," em ",[42,877,878],{},"float64",". O orçamento de erro fica bem abaixo de um ponto tipográfico mesmo em layouts profundos.",[19,881,882,883,887],{},"Se quiser ver toda a cadeia, ",[78,884,886],{"href":885},"/pt/blog/why-gpdf-is-faster","por que gpdf é 10× mais rápido que as alternativas"," cobre o pipeline de render. A grade é uma das camadas mais baratas — em M1, uma página leva uns 13 µs e a grade aporta apenas algumas centenas de nanossegundos.",[14,889,891],{"id":890},"um-exemplo-completo-e-funcional","Um exemplo completo e funcional",[19,893,894],{},"Cabeçalho 4/8, depois uma linha 12 com tabela, depois uma faixa de KPI 3/3/3/3:",[327,896,898],{"className":329,"code":897,"language":331,"meta":332,"style":332},"package main\n\nimport (\n    \"os\"\n\n    \"github.com/gpdf-dev/gpdf/document\"\n    \"github.com/gpdf-dev/gpdf/template\"\n)\n\nfunc main() {\n    doc := template.NewDocument(document.PageSize(document.A4))\n\n    doc.Page(func(p *template.PageBuilder) {\n        // Divisão 4/8: logo à esquerda, endereço à direita.\n        p.AutoRow(func(r *template.RowBuilder) {\n            r.Col(4, func(c *template.ColBuilder) {\n                c.Text(\"ACME, Ltda.\", template.FontSize(18), template.Bold())\n            })\n            r.Col(8, func(c *template.ColBuilder) {\n                c.Text(\"Av. Industrial, 123\", template.AlignRight())\n                c.Text(\"São Paulo - SP, 01000-000\", template.AlignRight())\n            })\n        })\n\n        p.Spacer(document.Mm(10))\n\n        // Linha 12 (uma coluna span 12) para uma tabela.\n        p.AutoRow(func(r *template.RowBuilder) {\n            r.Col(12, func(c *template.ColBuilder) {\n                c.Table([]string{\"Item\", \"Qtd.\", \"Preço\"}, [][]string{\n                    {\"Widget A\", \"2\", \"R$ 10,00\"},\n                    {\"Widget B\", \"1\", \"R$ 25,00\"},\n                })\n            })\n        })\n\n        p.Spacer(document.Mm(10))\n\n        // Faixa de KPI: 3 span × 4 colunas\n        kpis := []struct{ label, value string }{\n            {\"Subtotal\", \"R$ 45,00\"},\n            {\"ICMS (18%)\", \"R$ 8,10\"},\n            {\"Frete\", \"R$ 0,00\"},\n            {\"Total\", \"R$ 53,10\"},\n        }\n        p.AutoRow(func(r *template.RowBuilder) {\n            for _, k := range kpis {\n                k := k\n                r.Col(3, func(c *template.ColBuilder) {\n                    c.Text(k.label, template.FontSize(8))\n                    c.Text(k.value, template.FontSize(14), template.Bold())\n                })\n            }\n        })\n    })\n\n    f, _ := os.Create(\"invoice.pdf\")\n    defer f.Close()\n    doc.Render(f)\n}\n",[42,899,900,908,914,922,933,937,947,957,962,967,981,1019,1024,1052,1058,1084,1116,1162,1168,1200,1229,1257,1262,1268,1273,1299,1304,1310,1335,1367,1423,1457,1489,1495,1500,1505,1510,1533,1538,1544,1568,1592,1615,1638,1661,1667,1692,1714,1725,1757,1791,1832,1837,1843,1848,1853,1858,1890,1907,1924],{"__ignoreMap":332},[336,901,902,905],{"class":338,"line":339},[336,903,904],{"class":350},"package",[336,906,907],{"class":401}," main\n",[336,909,910],{"class":338,"line":369},[336,911,913],{"emptyLinePlaceholder":912},true,"\n",[336,915,916,919],{"class":338,"line":416},[336,917,918],{"class":342},"import",[336,920,921],{"class":350}," (\n",[336,923,924,927,930],{"class":338,"line":440},[336,925,926],{"class":350},"    \"",[336,928,929],{"class":401},"os",[336,931,932],{"class":350},"\"\n",[336,934,935],{"class":338,"line":446},[336,936,913],{"emptyLinePlaceholder":912},[336,938,940,942,945],{"class":338,"line":939},6,[336,941,926],{"class":350},[336,943,944],{"class":401},"github.com/gpdf-dev/gpdf/document",[336,946,932],{"class":350},[336,948,950,952,955],{"class":338,"line":949},7,[336,951,926],{"class":350},[336,953,954],{"class":401},"github.com/gpdf-dev/gpdf/template",[336,956,932],{"class":350},[336,958,960],{"class":338,"line":959},8,[336,961,437],{"class":350},[336,963,965],{"class":338,"line":964},9,[336,966,913],{"emptyLinePlaceholder":912},[336,968,970,973,976,979],{"class":338,"line":969},10,[336,971,972],{"class":350},"func",[336,974,975],{"class":378}," main",[336,977,978],{"class":350},"()",[336,980,413],{"class":350},[336,982,984,987,989,992,994,997,999,1002,1004,1007,1009,1011,1013,1016],{"class":338,"line":983},11,[336,985,986],{"class":346},"    doc ",[336,988,357],{"class":350},[336,990,991],{"class":346}," template",[336,993,375],{"class":350},[336,995,996],{"class":378},"NewDocument",[336,998,382],{"class":350},[336,1000,1001],{"class":346},"document",[336,1003,375],{"class":350},[336,1005,1006],{"class":378},"PageSize",[336,1008,382],{"class":350},[336,1010,1001],{"class":346},[336,1012,375],{"class":350},[336,1014,1015],{"class":346},"A4",[336,1017,1018],{"class":350},"))\n",[336,1020,1022],{"class":338,"line":1021},12,[336,1023,913],{"emptyLinePlaceholder":912},[336,1025,1027,1030,1032,1035,1037,1039,1041,1043,1045,1048,1050],{"class":338,"line":1026},13,[336,1028,1029],{"class":346},"    doc",[336,1031,375],{"class":350},[336,1033,1034],{"class":378},"Page",[336,1036,481],{"class":350},[336,1038,19],{"class":394},[336,1040,398],{"class":350},[336,1042,402],{"class":401},[336,1044,375],{"class":350},[336,1046,1047],{"class":401},"PageBuilder",[336,1049,410],{"class":350},[336,1051,413],{"class":350},[336,1053,1055],{"class":338,"line":1054},14,[336,1056,1057],{"class":606},"        // Divisão 4/8: logo à esquerda, endereço à direita.\n",[336,1059,1061,1064,1066,1068,1070,1072,1074,1076,1078,1080,1082],{"class":338,"line":1060},15,[336,1062,1063],{"class":346},"        p",[336,1065,375],{"class":350},[336,1067,478],{"class":378},[336,1069,481],{"class":350},[336,1071,484],{"class":394},[336,1073,398],{"class":350},[336,1075,402],{"class":401},[336,1077,375],{"class":350},[336,1079,493],{"class":401},[336,1081,410],{"class":350},[336,1083,413],{"class":350},[336,1085,1087,1090,1092,1094,1096,1098,1100,1102,1104,1106,1108,1110,1112,1114],{"class":338,"line":1086},16,[336,1088,1089],{"class":346},"            r",[336,1091,375],{"class":350},[336,1093,379],{"class":378},[336,1095,382],{"class":350},[336,1097,510],{"class":385},[336,1099,351],{"class":350},[336,1101,391],{"class":350},[336,1103,395],{"class":394},[336,1105,398],{"class":350},[336,1107,402],{"class":401},[336,1109,375],{"class":350},[336,1111,407],{"class":401},[336,1113,410],{"class":350},[336,1115,413],{"class":350},[336,1117,1119,1122,1124,1126,1128,1130,1133,1135,1137,1139,1141,1144,1146,1149,1152,1154,1156,1159],{"class":338,"line":1118},17,[336,1120,1121],{"class":346},"                c",[336,1123,375],{"class":350},[336,1125,424],{"class":378},[336,1127,382],{"class":350},[336,1129,541],{"class":350},[336,1131,1132],{"class":544},"ACME, Ltda.",[336,1134,541],{"class":350},[336,1136,351],{"class":350},[336,1138,991],{"class":346},[336,1140,375],{"class":350},[336,1142,1143],{"class":378},"FontSize",[336,1145,382],{"class":350},[336,1147,1148],{"class":385},"18",[336,1150,1151],{"class":350},"),",[336,1153,991],{"class":346},[336,1155,375],{"class":350},[336,1157,1158],{"class":378},"Bold",[336,1160,1161],{"class":350},"())\n",[336,1163,1165],{"class":338,"line":1164},18,[336,1166,1167],{"class":350},"            })\n",[336,1169,1171,1173,1175,1177,1179,1182,1184,1186,1188,1190,1192,1194,1196,1198],{"class":338,"line":1170},19,[336,1172,1089],{"class":346},[336,1174,375],{"class":350},[336,1176,379],{"class":378},[336,1178,382],{"class":350},[336,1180,1181],{"class":385},"8",[336,1183,351],{"class":350},[336,1185,391],{"class":350},[336,1187,395],{"class":394},[336,1189,398],{"class":350},[336,1191,402],{"class":401},[336,1193,375],{"class":350},[336,1195,407],{"class":401},[336,1197,410],{"class":350},[336,1199,413],{"class":350},[336,1201,1203,1205,1207,1209,1211,1213,1216,1218,1220,1222,1224,1227],{"class":338,"line":1202},20,[336,1204,1121],{"class":346},[336,1206,375],{"class":350},[336,1208,424],{"class":378},[336,1210,382],{"class":350},[336,1212,541],{"class":350},[336,1214,1215],{"class":544},"Av. Industrial, 123",[336,1217,541],{"class":350},[336,1219,351],{"class":350},[336,1221,991],{"class":346},[336,1223,375],{"class":350},[336,1225,1226],{"class":378},"AlignRight",[336,1228,1161],{"class":350},[336,1230,1232,1234,1236,1238,1240,1242,1245,1247,1249,1251,1253,1255],{"class":338,"line":1231},21,[336,1233,1121],{"class":346},[336,1235,375],{"class":350},[336,1237,424],{"class":378},[336,1239,382],{"class":350},[336,1241,541],{"class":350},[336,1243,1244],{"class":544},"São Paulo - SP, 01000-000",[336,1246,541],{"class":350},[336,1248,351],{"class":350},[336,1250,991],{"class":346},[336,1252,375],{"class":350},[336,1254,1226],{"class":378},[336,1256,1161],{"class":350},[336,1258,1260],{"class":338,"line":1259},22,[336,1261,1167],{"class":350},[336,1263,1265],{"class":338,"line":1264},23,[336,1266,1267],{"class":350},"        })\n",[336,1269,1271],{"class":338,"line":1270},24,[336,1272,913],{"emptyLinePlaceholder":912},[336,1274,1276,1278,1280,1283,1285,1287,1289,1292,1294,1297],{"class":338,"line":1275},25,[336,1277,1063],{"class":346},[336,1279,375],{"class":350},[336,1281,1282],{"class":378},"Spacer",[336,1284,382],{"class":350},[336,1286,1001],{"class":346},[336,1288,375],{"class":350},[336,1290,1291],{"class":378},"Mm",[336,1293,382],{"class":350},[336,1295,1296],{"class":385},"10",[336,1298,1018],{"class":350},[336,1300,1302],{"class":338,"line":1301},26,[336,1303,913],{"emptyLinePlaceholder":912},[336,1305,1307],{"class":338,"line":1306},27,[336,1308,1309],{"class":606},"        // Linha 12 (uma coluna span 12) para uma tabela.\n",[336,1311,1313,1315,1317,1319,1321,1323,1325,1327,1329,1331,1333],{"class":338,"line":1312},28,[336,1314,1063],{"class":346},[336,1316,375],{"class":350},[336,1318,478],{"class":378},[336,1320,481],{"class":350},[336,1322,484],{"class":394},[336,1324,398],{"class":350},[336,1326,402],{"class":401},[336,1328,375],{"class":350},[336,1330,493],{"class":401},[336,1332,410],{"class":350},[336,1334,413],{"class":350},[336,1336,1338,1340,1342,1344,1346,1349,1351,1353,1355,1357,1359,1361,1363,1365],{"class":338,"line":1337},29,[336,1339,1089],{"class":346},[336,1341,375],{"class":350},[336,1343,379],{"class":378},[336,1345,382],{"class":350},[336,1347,1348],{"class":385},"12",[336,1350,351],{"class":350},[336,1352,391],{"class":350},[336,1354,395],{"class":394},[336,1356,398],{"class":350},[336,1358,402],{"class":401},[336,1360,375],{"class":350},[336,1362,407],{"class":401},[336,1364,410],{"class":350},[336,1366,413],{"class":350},[336,1368,1370,1372,1374,1377,1380,1384,1387,1389,1392,1394,1396,1399,1402,1404,1406,1408,1411,1413,1416,1419,1421],{"class":338,"line":1369},30,[336,1371,1121],{"class":346},[336,1373,375],{"class":350},[336,1375,1376],{"class":378},"Table",[336,1378,1379],{"class":350},"([]",[336,1381,1383],{"class":1382},"spNyl","string",[336,1385,1386],{"class":350},"{",[336,1388,541],{"class":350},[336,1390,1391],{"class":544},"Item",[336,1393,541],{"class":350},[336,1395,351],{"class":350},[336,1397,1398],{"class":350}," \"",[336,1400,1401],{"class":544},"Qtd.",[336,1403,541],{"class":350},[336,1405,351],{"class":350},[336,1407,1398],{"class":350},[336,1409,1410],{"class":544},"Preço",[336,1412,541],{"class":350},[336,1414,1415],{"class":350},"},",[336,1417,1418],{"class":350}," [][]",[336,1420,1383],{"class":1382},[336,1422,366],{"class":350},[336,1424,1426,1429,1431,1434,1436,1438,1440,1443,1445,1447,1449,1452,1454],{"class":338,"line":1425},31,[336,1427,1428],{"class":350},"                    {",[336,1430,541],{"class":350},[336,1432,1433],{"class":544},"Widget A",[336,1435,541],{"class":350},[336,1437,351],{"class":350},[336,1439,1398],{"class":350},[336,1441,1442],{"class":544},"2",[336,1444,541],{"class":350},[336,1446,351],{"class":350},[336,1448,1398],{"class":350},[336,1450,1451],{"class":544},"R$ 10,00",[336,1453,541],{"class":350},[336,1455,1456],{"class":350},"},\n",[336,1458,1460,1462,1464,1467,1469,1471,1473,1476,1478,1480,1482,1485,1487],{"class":338,"line":1459},32,[336,1461,1428],{"class":350},[336,1463,541],{"class":350},[336,1465,1466],{"class":544},"Widget B",[336,1468,541],{"class":350},[336,1470,351],{"class":350},[336,1472,1398],{"class":350},[336,1474,1475],{"class":544},"1",[336,1477,541],{"class":350},[336,1479,351],{"class":350},[336,1481,1398],{"class":350},[336,1483,1484],{"class":544},"R$ 25,00",[336,1486,541],{"class":350},[336,1488,1456],{"class":350},[336,1490,1492],{"class":338,"line":1491},33,[336,1493,1494],{"class":350},"                })\n",[336,1496,1498],{"class":338,"line":1497},34,[336,1499,1167],{"class":350},[336,1501,1503],{"class":338,"line":1502},35,[336,1504,1267],{"class":350},[336,1506,1508],{"class":338,"line":1507},36,[336,1509,913],{"emptyLinePlaceholder":912},[336,1511,1513,1515,1517,1519,1521,1523,1525,1527,1529,1531],{"class":338,"line":1512},37,[336,1514,1063],{"class":346},[336,1516,375],{"class":350},[336,1518,1282],{"class":378},[336,1520,382],{"class":350},[336,1522,1001],{"class":346},[336,1524,375],{"class":350},[336,1526,1291],{"class":378},[336,1528,382],{"class":350},[336,1530,1296],{"class":385},[336,1532,1018],{"class":350},[336,1534,1536],{"class":338,"line":1535},38,[336,1537,913],{"emptyLinePlaceholder":912},[336,1539,1541],{"class":338,"line":1540},39,[336,1542,1543],{"class":606},"        // Faixa de KPI: 3 span × 4 colunas\n",[336,1545,1547,1550,1552,1555,1558,1560,1563,1565],{"class":338,"line":1546},40,[336,1548,1549],{"class":346},"        kpis ",[336,1551,357],{"class":350},[336,1553,1554],{"class":350}," []struct{",[336,1556,1557],{"class":346}," label",[336,1559,351],{"class":350},[336,1561,1562],{"class":346}," value ",[336,1564,1383],{"class":1382},[336,1566,1567],{"class":350}," }{\n",[336,1569,1571,1574,1576,1579,1581,1583,1585,1588,1590],{"class":338,"line":1570},41,[336,1572,1573],{"class":350},"            {",[336,1575,541],{"class":350},[336,1577,1578],{"class":544},"Subtotal",[336,1580,541],{"class":350},[336,1582,351],{"class":350},[336,1584,1398],{"class":350},[336,1586,1587],{"class":544},"R$ 45,00",[336,1589,541],{"class":350},[336,1591,1456],{"class":350},[336,1593,1595,1597,1599,1602,1604,1606,1608,1611,1613],{"class":338,"line":1594},42,[336,1596,1573],{"class":350},[336,1598,541],{"class":350},[336,1600,1601],{"class":544},"ICMS (18%)",[336,1603,541],{"class":350},[336,1605,351],{"class":350},[336,1607,1398],{"class":350},[336,1609,1610],{"class":544},"R$ 8,10",[336,1612,541],{"class":350},[336,1614,1456],{"class":350},[336,1616,1618,1620,1622,1625,1627,1629,1631,1634,1636],{"class":338,"line":1617},43,[336,1619,1573],{"class":350},[336,1621,541],{"class":350},[336,1623,1624],{"class":544},"Frete",[336,1626,541],{"class":350},[336,1628,351],{"class":350},[336,1630,1398],{"class":350},[336,1632,1633],{"class":544},"R$ 0,00",[336,1635,541],{"class":350},[336,1637,1456],{"class":350},[336,1639,1641,1643,1645,1648,1650,1652,1654,1657,1659],{"class":338,"line":1640},44,[336,1642,1573],{"class":350},[336,1644,541],{"class":350},[336,1646,1647],{"class":544},"Total",[336,1649,541],{"class":350},[336,1651,351],{"class":350},[336,1653,1398],{"class":350},[336,1655,1656],{"class":544},"R$ 53,10",[336,1658,541],{"class":350},[336,1660,1456],{"class":350},[336,1662,1664],{"class":338,"line":1663},45,[336,1665,1666],{"class":350},"        }\n",[336,1668,1670,1672,1674,1676,1678,1680,1682,1684,1686,1688,1690],{"class":338,"line":1669},46,[336,1671,1063],{"class":346},[336,1673,375],{"class":350},[336,1675,478],{"class":378},[336,1677,481],{"class":350},[336,1679,484],{"class":394},[336,1681,398],{"class":350},[336,1683,402],{"class":401},[336,1685,375],{"class":350},[336,1687,493],{"class":401},[336,1689,410],{"class":350},[336,1691,413],{"class":350},[336,1693,1695,1698,1700,1702,1705,1707,1709,1712],{"class":338,"line":1694},47,[336,1696,1697],{"class":342},"            for",[336,1699,347],{"class":346},[336,1701,351],{"class":350},[336,1703,1704],{"class":346}," k ",[336,1706,357],{"class":350},[336,1708,360],{"class":342},[336,1710,1711],{"class":346}," kpis ",[336,1713,366],{"class":350},[336,1715,1717,1720,1722],{"class":338,"line":1716},48,[336,1718,1719],{"class":346},"                k ",[336,1721,357],{"class":350},[336,1723,1724],{"class":346}," k\n",[336,1726,1728,1731,1733,1735,1737,1739,1741,1743,1745,1747,1749,1751,1753,1755],{"class":338,"line":1727},49,[336,1729,1730],{"class":346},"                r",[336,1732,375],{"class":350},[336,1734,379],{"class":378},[336,1736,382],{"class":350},[336,1738,386],{"class":385},[336,1740,351],{"class":350},[336,1742,391],{"class":350},[336,1744,395],{"class":394},[336,1746,398],{"class":350},[336,1748,402],{"class":401},[336,1750,375],{"class":350},[336,1752,407],{"class":401},[336,1754,410],{"class":350},[336,1756,413],{"class":350},[336,1758,1760,1763,1765,1767,1769,1772,1774,1777,1779,1781,1783,1785,1787,1789],{"class":338,"line":1759},50,[336,1761,1762],{"class":346},"                    c",[336,1764,375],{"class":350},[336,1766,424],{"class":378},[336,1768,382],{"class":350},[336,1770,1771],{"class":346},"k",[336,1773,375],{"class":350},[336,1775,1776],{"class":346},"label",[336,1778,351],{"class":350},[336,1780,991],{"class":346},[336,1782,375],{"class":350},[336,1784,1143],{"class":378},[336,1786,382],{"class":350},[336,1788,1181],{"class":385},[336,1790,1018],{"class":350},[336,1792,1794,1796,1798,1800,1802,1804,1806,1809,1811,1813,1815,1817,1819,1822,1824,1826,1828,1830],{"class":338,"line":1793},51,[336,1795,1762],{"class":346},[336,1797,375],{"class":350},[336,1799,424],{"class":378},[336,1801,382],{"class":350},[336,1803,1771],{"class":346},[336,1805,375],{"class":350},[336,1807,1808],{"class":346},"value",[336,1810,351],{"class":350},[336,1812,991],{"class":346},[336,1814,375],{"class":350},[336,1816,1143],{"class":378},[336,1818,382],{"class":350},[336,1820,1821],{"class":385},"14",[336,1823,1151],{"class":350},[336,1825,991],{"class":346},[336,1827,375],{"class":350},[336,1829,1158],{"class":378},[336,1831,1161],{"class":350},[336,1833,1835],{"class":338,"line":1834},52,[336,1836,1494],{"class":350},[336,1838,1840],{"class":338,"line":1839},53,[336,1841,1842],{"class":350},"            }\n",[336,1844,1846],{"class":338,"line":1845},54,[336,1847,1267],{"class":350},[336,1849,1851],{"class":338,"line":1850},55,[336,1852,443],{"class":350},[336,1854,1856],{"class":338,"line":1855},56,[336,1857,913],{"emptyLinePlaceholder":912},[336,1859,1861,1864,1866,1869,1871,1874,1876,1879,1881,1883,1886,1888],{"class":338,"line":1860},57,[336,1862,1863],{"class":346},"    f",[336,1865,351],{"class":350},[336,1867,1868],{"class":346}," _ ",[336,1870,357],{"class":350},[336,1872,1873],{"class":346}," os",[336,1875,375],{"class":350},[336,1877,1878],{"class":378},"Create",[336,1880,382],{"class":350},[336,1882,541],{"class":350},[336,1884,1885],{"class":544},"invoice.pdf",[336,1887,541],{"class":350},[336,1889,437],{"class":350},[336,1891,1893,1896,1899,1901,1904],{"class":338,"line":1892},58,[336,1894,1895],{"class":342},"    defer",[336,1897,1898],{"class":346}," f",[336,1900,375],{"class":350},[336,1902,1903],{"class":378},"Close",[336,1905,1906],{"class":350},"()\n",[336,1908,1910,1912,1914,1917,1919,1922],{"class":338,"line":1909},59,[336,1911,1029],{"class":346},[336,1913,375],{"class":350},[336,1915,1916],{"class":378},"Render",[336,1918,382],{"class":350},[336,1920,1921],{"class":346},"f",[336,1923,437],{"class":350},[336,1925,1927],{"class":338,"line":1926},60,[336,1928,449],{"class":350},[19,1930,1931,1932,1935,1936,1938],{},"É um programa que roda. ",[42,1933,1934],{},"go get github.com/gpdf-dev/gpdf"," e executa; o arquivo ",[42,1937,1885],{}," aparece na pasta. Tempo de render em M1: cerca de 130 µs.",[14,1940,1942],{"id":1941},"quando-o-modelo-inteiro-está-errado","Quando o modelo inteiro está errado",[19,1944,1945],{},"O modelo de doze avos inteiros é genuinamente a escolha errada em dois casos. Lista honesta, porque você vai esbarrar em pelo menos um:",[51,1947,1948,1965],{},[54,1949,1950,1953,1954,1956,1957,1960,1961,1964],{},[22,1951,1952],{},"Você precisa de larguras com precisão de pixel."," «Esta coluna tem que medir exatamente 73,5pt.» ",[42,1955,874],{}," não te entrega isso, porque ",[42,1958,1959],{},"73,5 / total × 12"," raramente é inteiro. Use ",[42,1962,1963],{},"page.Absolute(...)"," para os poucos elementos com coordenada fixa e deixe o resto para a grade. Misturar os dois na mesma página é tranquilo.",[54,1966,1967,1970],{},[22,1968,1969],{},"Você precisa de fluxo de colunas estilo jornal."," Um parágrafo enche uma coluna e continua na próxima. A grade não faz isso. Ainda não temos motor de fluxo de texto entre colunas. Se precisar, abra um issue — sabemos que falta.",[19,1972,1973],{},"Para o resto — faturas, relatórios, contratos, brochuras, decks — a grade de 12 encaixa mais justa que CSS, não mais frouxa.",[14,1975,1977],{"id":1976},"perguntas-frequentes","Perguntas frequentes",[19,1979,1980,1983,1984,1987],{},[22,1981,1982],{},"P: Posso trocar o 12 por outro valor, tipo 24?","\nNão. ",[42,1985,1986],{},"gridColumns"," é constante. Trocar invalidaria todos os templates existentes. Decidimos 12 uma vez e ficamos.",[19,1989,1990,1993,1994,1997,1998,2001,2002,2005],{},[22,1991,1992],{},"P: E se eu quiser aninhar uma linha dentro de uma coluna?","\nPode. ",[42,1995,1996],{},"c.AutoRow(...)"," cria uma sub-linha dentro da coluna. Os spans dentro da sub-linha são 1–12 da ",[30,1999,2000],{},"largura da coluna pai",", não da página. A aninhação compõe limpa porque cada nível é só ",[42,2003,2004],{},"Pct(span/12 × 100)"," do pai.",[19,2007,2008,2011,2012,2015],{},[22,2009,2010],{},"P: Funciona em páginas em paisagem?","\nSim. A grade é agnóstica a tamanho de página. ",[42,2013,2014],{},"r.Col(6, ...)"," é metade da linha tendo ela 210mm (A4 retrato) ou 297mm (A4 paisagem).",[19,2017,2018,2025,2026,2029],{},[22,2019,2020,2021,2024],{},"P: Por que não tem um atalho ",[42,2022,2023],{},"r.Col2(span, span, fn1, fn2)"," para duas colunas?","\nPorque trocar uma linha por mais superfície de API é troca ruim. Se você se pega repetindo um padrão de linha, escreva uma função Go que receba ",[42,2027,2028],{},"*template.PageBuilder"," e o adicione. A grade fica mínima para que padrões do usuário cresçam sem conflito.",[19,2031,2032,2039],{},[22,2033,2034,2035,2038],{},"P: E ",[42,2036,2037],{},"grid-area"," e linhas nomeadas do CSS Grid?","\nNão estão no gpdf nem no roadmap. O custo-benefício não fecha para PDFs.",[14,2041,2043],{"id":2042},"resumo","Resumo",[19,2045,2046,2047,2050],{},"A grade de 12 colunas é a primitiva de layout mais enxuta que cobre as divisões de que documentos reais precisam. Pegamos o número emprestado do Bootstrap, mantivemos o modelo inteiro e descartamos breakpoints, gutter, order, auto-fill, soma de span forçada e o resto da bagagem do responsivo web. Sobrou uma constante, um método de builder e uma fórmula de largura — cerca de 30 linhas de Go. Compõe por aninhamento, convive com ",[42,2048,2049],{},"Absolute"," para os poucos casos em que a grade não dá conta, e nunca rebalanceia em silêncio o que você escreveu.",[14,2052,2054],{"id":2053},"experimente-o-gpdf","Experimente o gpdf",[19,2056,2057],{},"gpdf é uma biblioteca Go para PDF: MIT, sem dependências, suporte CJK pronto.",[327,2059,2063],{"className":2060,"code":2061,"language":2062,"meta":332,"style":332},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com/gpdf-dev/gpdf\n","bash",[42,2064,2065],{"__ignoreMap":332},[336,2066,2067,2069,2072],{"class":338,"line":339},[336,2068,331],{"class":401},[336,2070,2071],{"class":544}," get",[336,2073,2074],{"class":544}," github.com/gpdf-dev/gpdf\n",[19,2076,2077,2083,2084],{},[78,2078,2082],{"href":2079,"rel":2080},"https://github.com/gpdf-dev/gpdf",[2081],"nofollow","⭐ Star no GitHub"," · ",[78,2085,2088],{"href":2086,"rel":2087},"https://gpdf.dev/pt/docs/quickstart",[2081],"Ler a documentação",[14,2090,2092],{"id":2091},"o-que-ler-em-seguida","O que ler em seguida",[136,2094,2095,2101,2107],{},[54,2096,2097,2100],{},[78,2098,2099],{"href":80},"Como funciona a grade de 12 colunas no gpdf?"," — versão receita, com mais padrões de código",[54,2102,2103,2106],{},[78,2104,2105],{"href":885},"Por que gpdf é 10× mais rápido que as alternativas"," — internals do pipeline de render",[54,2108,2109,2113],{},[78,2110,2112],{"href":2111},"/pt/docs/quickstart","Quickstart"," — gere seu primeiro PDF em cinco minutos",[2115,2116,2117],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}",{"title":332,"searchDepth":369,"depth":369,"links":2119},[2120,2121,2122,2123,2124,2125,2133,2134,2135,2136,2137,2138,2139,2140],{"id":16,"depth":369,"text":17},{"id":36,"depth":369,"text":37},{"id":89,"depth":369,"text":90},{"id":130,"depth":369,"text":131},{"id":198,"depth":369,"text":199},{"id":231,"depth":369,"text":232,"children":2126},[2127,2128,2129,2130,2131,2132],{"id":236,"depth":416,"text":237},{"id":274,"depth":416,"text":275},{"id":291,"depth":416,"text":292},{"id":306,"depth":416,"text":307},{"id":455,"depth":416,"text":456},{"id":646,"depth":416,"text":647},{"id":666,"depth":369,"text":667},{"id":840,"depth":369,"text":841},{"id":890,"depth":369,"text":891},{"id":1941,"depth":369,"text":1942},{"id":1976,"depth":369,"text":1977},{"id":2042,"depth":369,"text":2043},{"id":2053,"depth":369,"text":2054},{"id":2091,"depth":369,"text":2092},"2026-04-29","gpdf adota a grade de 12 colunas do Bootstrap para diagramar PDFs. Por que 12, o que mantemos do modelo web e o que descartamos sem dó.",false,"md",null,{},"/pt/blog/bootstrap-grid-thinking-for-pdf",{"title":5,"description":2142},"pt/blog/017.bootstrap-grid-thinking-for-pdf",[2151,2152,2153],"internals","templates","comparison","w93UWMaCVOpGXwu9FVF33ByVkNfFBmjxCGg4yP9J0Hc",1779199037363]