SSB-data (tabeller 14061 og 14067) som viser at: - 41 % av fattigste kvartil bruker >40 % av inntekten på bolig (vs 7 % rikeste) - 17 % av fattigste bruker 60 %+ av inntekten bare på bolig - 82 % av sosialhjelpsmottakere leier — bygger ingen formue - Byrden har økt kraftig for alle grupper etter rentehoppet i 2022 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
262 lines
8.5 KiB
JavaScript
262 lines
8.5 KiB
JavaScript
// SSB data: Boutgifter og boligeierskap etter inntekt
|
||
// Tabell 14061: Boligøkonomi etter inntektsgruppe (boutgifter som andel av inntekt)
|
||
// Tabell 14067: Boligeierskap etter inntektsgruppe
|
||
// Hentet 2026-03-16 via SSB PxWeb API v2
|
||
|
||
// --- Data ---
|
||
|
||
const YEARS = ['2015', '2016', '2017', '2018', '2019', '2020', '2021', '2022', '2023', '2024'];
|
||
|
||
// Boutgifter som andel av inntekt per kvartil, 2024 (tabell 14061)
|
||
const QUARTILE_LABELS = ['Laveste kvartil', 'Andre kvartil', 'Tredje kvartil', 'Høyeste kvartil'];
|
||
|
||
const HOUSING_BURDEN = {
|
||
under10: [ 5.2, 10.8, 16.6, 22.0],
|
||
from10to19: [12.4, 26.1, 22.8, 24.6],
|
||
from20to29: [19.3, 28.2, 29.0, 28.2],
|
||
from30to39: [22.4, 19.5, 18.9, 17.7],
|
||
from40to59: [23.6, 12.7, 11.5, 6.4],
|
||
over60: [17.1, 2.8, 1.2, 1.0]
|
||
};
|
||
|
||
// Andel med boutgifter >40% av inntekt (40-59% + 60%+) over tid (tabell 14061)
|
||
const HEAVY_BURDEN = {
|
||
q1: [33.6, 33.4, 32.9, 34.5, 33.8, 33.5, 35.6, 41.8, 42.9, 40.7],
|
||
q2: [ 7.3, 7.0, 7.0, 6.3, 8.3, 6.0, 7.6, 12.3, 12.5, 15.5],
|
||
q3: [ 4.2, 3.1, 4.2, 3.9, 3.2, 3.6, 3.6, 6.0, 9.3, 12.7],
|
||
q4: [ 2.5, 1.2, 1.9, 2.5, 2.5, 3.5, 2.5, 4.6, 5.9, 7.4]
|
||
};
|
||
|
||
// Eierskap etter inntektsgruppe og utsatte grupper, 2024 (tabell 14067)
|
||
const OWNERSHIP_GROUPS = [
|
||
{ name: 'Sosialhjelpsmottakere', selveier: 13.9, andel: 4.6, leier: 81.5 },
|
||
{ name: 'Lavinntekt (EU 60 %)', selveier: 21.2, andel: 10.8, leier: 68.0 },
|
||
{ name: 'Laveste kvartil', selveier: 33.2, andel: 12.6, leier: 54.3 },
|
||
{ name: 'Barnefamilier lav inntekt', selveier: 39.0, andel: 8.5, leier: 52.5 },
|
||
{ name: 'Aleneboende eldre lav innt.', selveier: 52.4, andel: 23.9, leier: 23.7 },
|
||
{ name: 'Uføretrygdede', selveier: 55.6, andel: 13.7, leier: 30.7 },
|
||
{ name: 'Andre kvartil', selveier: 60.3, andel: 18.2, leier: 21.5 },
|
||
{ name: 'Tredje kvartil', selveier: 70.2, andel: 15.6, leier: 14.2 },
|
||
{ name: 'Høyeste kvartil', selveier: 79.7, andel: 13.6, leier: 6.7 },
|
||
];
|
||
|
||
// --- Formattering ---
|
||
|
||
function fmtPct(n) {
|
||
return n.toLocaleString('nb-NO', { minimumFractionDigits: 1, maximumFractionDigits: 1 }) + '\u202f%';
|
||
}
|
||
|
||
const GRID_COLOR = 'rgba(0,0,0,0.06)';
|
||
const TICK_COLOR = '#8a857e';
|
||
|
||
function baseOpts() {
|
||
return {
|
||
responsive: true, maintainAspectRatio: false,
|
||
plugins: {
|
||
legend: { display: false },
|
||
tooltip: {
|
||
backgroundColor: '#1a1714',
|
||
titleColor: '#f5f2eb',
|
||
bodyColor: 'rgba(245,242,235,0.7)',
|
||
padding: 10,
|
||
cornerRadius: 4,
|
||
titleFont: { family: 'DM Sans', size: 12 },
|
||
bodyFont: { family: 'DM Sans', size: 12 }
|
||
}
|
||
},
|
||
scales: {
|
||
x: {
|
||
ticks: { color: TICK_COLOR, font: { size: 11, family: 'DM Sans' }, maxRotation: 0 },
|
||
grid: { display: false },
|
||
border: { color: 'rgba(0,0,0,0.1)' }
|
||
},
|
||
y: {
|
||
ticks: { color: TICK_COLOR, font: { size: 11, family: 'DM Sans' }, callback: v => v + ' %' },
|
||
grid: { color: GRID_COLOR },
|
||
border: { dash: [3, 3], color: 'transparent' }
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
// --- Diagram 1: Boutgifter som andel av inntekt (stablet horisontal) ---
|
||
|
||
var chart1Opts = baseOpts();
|
||
chart1Opts.indexAxis = 'y';
|
||
chart1Opts.scales = {
|
||
x: {
|
||
stacked: true,
|
||
max: 100,
|
||
ticks: { color: TICK_COLOR, font: { size: 11, family: 'DM Sans' }, callback: v => v + ' %' },
|
||
grid: { color: GRID_COLOR },
|
||
border: { dash: [3, 3], color: 'transparent' }
|
||
},
|
||
y: {
|
||
stacked: true,
|
||
ticks: { color: TICK_COLOR, font: { size: 11, family: 'DM Sans' }, autoSkip: false },
|
||
grid: { display: false },
|
||
border: { color: 'rgba(0,0,0,0.1)' }
|
||
}
|
||
};
|
||
chart1Opts.plugins.tooltip = {
|
||
mode: 'index',
|
||
callbacks: {
|
||
label: function(c) {
|
||
return ' ' + c.dataset.label + ': ' + fmtPct(c.parsed.x);
|
||
}
|
||
},
|
||
backgroundColor: '#1a1714',
|
||
titleColor: '#f5f2eb',
|
||
bodyColor: 'rgba(245,242,235,0.7)',
|
||
padding: 10,
|
||
cornerRadius: 4,
|
||
titleFont: { family: 'DM Sans', size: 12 },
|
||
bodyFont: { family: 'DM Sans', size: 12 }
|
||
};
|
||
|
||
new Chart(document.getElementById('chart1'), {
|
||
type: 'bar',
|
||
data: {
|
||
labels: QUARTILE_LABELS,
|
||
datasets: [
|
||
{ label: 'Under 10 %', data: HOUSING_BURDEN.under10, backgroundColor: '#2c6e49cc', borderColor: '#2c6e49', borderWidth: 1, borderRadius: 1 },
|
||
{ label: '10–19 %', data: HOUSING_BURDEN.from10to19, backgroundColor: '#27ae60cc', borderColor: '#27ae60', borderWidth: 1, borderRadius: 1 },
|
||
{ label: '20–29 %', data: HOUSING_BURDEN.from20to29, backgroundColor: '#e67e22cc', borderColor: '#e67e22', borderWidth: 1, borderRadius: 1 },
|
||
{ label: '30–39 %', data: HOUSING_BURDEN.from30to39, backgroundColor: '#e74c3ccc', borderColor: '#e74c3c', borderWidth: 1, borderRadius: 1 },
|
||
{ label: '40–59 %', data: HOUSING_BURDEN.from40to59, backgroundColor: '#c0392bcc', borderColor: '#c0392b', borderWidth: 1, borderRadius: 1 },
|
||
{ label: '60 %+', data: HOUSING_BURDEN.over60, backgroundColor: '#8b1a1acc', borderColor: '#8b1a1a', borderWidth: 1, borderRadius: 1 }
|
||
]
|
||
},
|
||
options: chart1Opts
|
||
});
|
||
|
||
// --- Diagram 2: Tung boutgiftsbyrde over tid (linje) ---
|
||
|
||
function buildLegend(containerId, items) {
|
||
var container = document.getElementById(containerId);
|
||
items.forEach(function(item) {
|
||
var span = document.createElement('span');
|
||
var swatch = document.createElement('span');
|
||
swatch.className = 'swatch';
|
||
swatch.style.background = item.color;
|
||
span.appendChild(swatch);
|
||
span.appendChild(document.createTextNode(item.name));
|
||
container.appendChild(span);
|
||
});
|
||
}
|
||
|
||
var chart2Lines = [
|
||
{ name: 'Laveste kvartil', data: HEAVY_BURDEN.q1, color: '#c0392b' },
|
||
{ name: 'Andre kvartil', data: HEAVY_BURDEN.q2, color: '#e67e22' },
|
||
{ name: 'Tredje kvartil', data: HEAVY_BURDEN.q3, color: '#1a4a8a' },
|
||
{ name: 'Høyeste kvartil', data: HEAVY_BURDEN.q4, color: '#2c6e49' }
|
||
];
|
||
|
||
buildLegend('legend2', chart2Lines);
|
||
|
||
var chart2Opts = baseOpts();
|
||
chart2Opts.scales.y.max = 50;
|
||
chart2Opts.plugins.tooltip = {
|
||
callbacks: {
|
||
label: function(c) {
|
||
return ' ' + c.dataset.label + ': ' + fmtPct(c.parsed.y);
|
||
}
|
||
},
|
||
backgroundColor: '#1a1714',
|
||
titleColor: '#f5f2eb',
|
||
bodyColor: 'rgba(245,242,235,0.7)',
|
||
padding: 10,
|
||
cornerRadius: 4,
|
||
titleFont: { family: 'DM Sans', size: 12 },
|
||
bodyFont: { family: 'DM Sans', size: 12 }
|
||
};
|
||
|
||
new Chart(document.getElementById('chart2'), {
|
||
type: 'line',
|
||
data: {
|
||
labels: YEARS,
|
||
datasets: chart2Lines.map(function(line) {
|
||
return {
|
||
label: line.name,
|
||
data: line.data,
|
||
borderColor: line.color,
|
||
backgroundColor: line.color + '12',
|
||
fill: false,
|
||
tension: 0.3,
|
||
pointRadius: 0,
|
||
pointHoverRadius: 4,
|
||
borderWidth: 2.5
|
||
};
|
||
})
|
||
},
|
||
options: chart2Opts
|
||
});
|
||
|
||
// --- Diagram 3: Eierskap etter inntektsgruppe (horisontal stablet) ---
|
||
|
||
var chart3Opts = baseOpts();
|
||
chart3Opts.indexAxis = 'y';
|
||
chart3Opts.scales = {
|
||
x: {
|
||
stacked: true,
|
||
max: 100,
|
||
ticks: { color: TICK_COLOR, font: { size: 11, family: 'DM Sans' }, callback: v => v + ' %' },
|
||
grid: { color: GRID_COLOR },
|
||
border: { dash: [3, 3], color: 'transparent' }
|
||
},
|
||
y: {
|
||
stacked: true,
|
||
ticks: { color: TICK_COLOR, font: { size: 11, family: 'DM Sans' }, autoSkip: false },
|
||
grid: { display: false },
|
||
border: { color: 'rgba(0,0,0,0.1)' }
|
||
}
|
||
};
|
||
chart3Opts.plugins.tooltip = {
|
||
mode: 'index',
|
||
callbacks: {
|
||
label: function(c) {
|
||
return ' ' + c.dataset.label + ': ' + fmtPct(c.parsed.x);
|
||
}
|
||
},
|
||
backgroundColor: '#1a1714',
|
||
titleColor: '#f5f2eb',
|
||
bodyColor: 'rgba(245,242,235,0.7)',
|
||
padding: 10,
|
||
cornerRadius: 4,
|
||
titleFont: { family: 'DM Sans', size: 12 },
|
||
bodyFont: { family: 'DM Sans', size: 12 }
|
||
};
|
||
|
||
new Chart(document.getElementById('chart3'), {
|
||
type: 'bar',
|
||
data: {
|
||
labels: OWNERSHIP_GROUPS.map(function(g) { return g.name; }),
|
||
datasets: [
|
||
{
|
||
label: 'Selveier',
|
||
data: OWNERSHIP_GROUPS.map(function(g) { return g.selveier; }),
|
||
backgroundColor: '#2c6e49cc',
|
||
borderColor: '#2c6e49',
|
||
borderWidth: 1,
|
||
borderRadius: 2
|
||
},
|
||
{
|
||
label: 'Andelseier',
|
||
data: OWNERSHIP_GROUPS.map(function(g) { return g.andel; }),
|
||
backgroundColor: '#1a4a8acc',
|
||
borderColor: '#1a4a8a',
|
||
borderWidth: 1,
|
||
borderRadius: 2
|
||
},
|
||
{
|
||
label: 'Leier',
|
||
data: OWNERSHIP_GROUPS.map(function(g) { return g.leier; }),
|
||
backgroundColor: '#c0392bcc',
|
||
borderColor: '#c0392b',
|
||
borderWidth: 1,
|
||
borderRadius: 2
|
||
}
|
||
]
|
||
},
|
||
options: chart3Opts
|
||
});
|