Weerwidget met eigen iconen Nieuw
Rustige weerwidget met voorbeeldweer voor Rotterdam: temperatuur nu, korte verwachting en tabs voor komende uren of komende dagen (toegankelijke tablist met pijltjestoetsen). De iconen zijn eigen SVG-lijntekeningen die heel licht bewegen (zon draait, wolk drijft, regen valt) en stilstaan bij reduced motion. Voor recreatie, horeca met terras, evenementen, bouw en hoveniers; koppel hem aan een weer-API.
Rotterdam · voorbeeldweer, do 14:20
14°
Half bewolkt, vanaf 17:00 regen
Zo gebruik je het
- Plak de HTML op de plek waar het onderdeel moet komen.
- Zet de CSS in je stylesheet. Alle klassen hebben een eigen voorvoegsel, dus niets botst met je eigen opmaak.
- Voeg de JavaScript toe en roep init() aan met het element waar de HTML in staat.
<!-- Weerwidget met eigen iconen · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="wtr">
<div class="wtr__now"><div class="wtr__txt"><p class="wtr__plaats"><b>Rotterdam</b> · voorbeeldweer, do 14:20</p><p class="wtr__temp">14°</p><p class="wtr__desc">Half bewolkt, vanaf 17:00 regen</p></div><div class="wtr__big" aria-hidden="true"></div></div>
<div class="wtr__tabs" role="tablist" aria-label="Verwachting"><button type="button" role="tab" aria-selected="true" data-p="u">Komende uren</button><button type="button" role="tab" aria-selected="false" tabindex="-1" data-p="d">Komende dagen</button></div>
<ul class="wtr__list" role="tabpanel"></ul>
</div>
</div>/* Weerwidget met eigen iconen · NedDev · eigen werk. */
.wtr{position:absolute;inset:0;box-sizing:border-box;padding:12px 14px;background:#fff;color:#0a0a0a;font-family:'Switzer',sans-serif;display:flex;flex-direction:column;justify-content:center;gap:8px;container-type:inline-size}
.wtr__now{display:flex;justify-content:space-between;align-items:center;gap:10px}
.wtr__txt p{margin:0}
.wtr__plaats{font-size:12px;color:#5f5e5a}
.wtr__plaats b{color:#0a0a0a;font-weight:600;font-size:13px}
.wtr__temp{font-size:38px;font-weight:600;line-height:1.05;letter-spacing:-.02em}
.wtr__desc{font-size:13px;color:#3d3c39}
.wtr__big{width:72px;height:72px;flex:none}
.wtr__big svg,.wtr__ic svg{width:100%;height:100%;display:block;overflow:visible}
.wtr__tabs{display:flex;gap:14px;border-bottom:1px solid #e3e1dd}
.wtr__tabs button{min-height:26px;padding:0;border:0;border-bottom:2px solid transparent;margin-bottom:-1px;background:none;color:#6b6a66;font:500 12px 'Switzer',sans-serif;cursor:pointer}
.wtr__tabs button:hover{color:#0a0a0a}
.wtr__tabs button[aria-selected="true"]{color:#0a0a0a;font-weight:600;border-bottom-color:#F5480F}
.wtr__tabs button:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.wtr__list{list-style:none;margin:0;padding:4px 0 0;display:flex;justify-content:space-between;align-items:center}
.wtr__list:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.wtr__it{display:flex;flex-direction:column;align-items:center;gap:2px;min-width:0;flex:1 1 0;animation:wtr-in .35s ease both;animation-delay:calc(var(--i)*40ms)}
.wtr__tm{font-size:12px;color:#6b6a66}
.wtr__ic{width:26px;height:26px}
.wtr__tp{font-size:13px;font-weight:600;font-variant-numeric:tabular-nums;white-space:nowrap}
.wtr__tp small{font-size:12px;font-weight:400;color:#8a8883}
.ic-l{fill:none;stroke:#0a0a0a;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
.ic-c{fill:#fff;stroke:#0a0a0a;stroke-width:1.5;stroke-linejoin:round}
.ic-s{fill:#F5480F}
.ic-r{stroke:#F5480F}
.ic-d{stroke:#0a0a0a;stroke-width:1.5;stroke-linecap:round}
.wtr__big .ic-rays{animation:wtr-spin 40s linear infinite}
.wtr__big .ic-cl{animation:wtr-drift 7s ease-in-out infinite alternate}
.wtr__big .ic-d{animation:wtr-drop 1.4s ease-in infinite}
.wtr__big .ic-d:nth-child(2){animation-delay:.45s}.wtr__big .ic-d:nth-child(3){animation-delay:.9s}
@keyframes wtr-spin{to{transform:rotate(360deg)}}
@keyframes wtr-drift{from{transform:translateX(-.8px)}to{transform:translateX(.8px)}}
@keyframes wtr-drop{0%{transform:translateY(-1px);opacity:0}30%{opacity:1}100%{transform:translateY(3px);opacity:0}}
@keyframes wtr-in{from{opacity:0;transform:translateY(4px)}}
@container (max-width:380px){.wtr__temp{font-size:32px}.wtr__big{width:58px;height:58px}.wtr__ic{width:22px;height:22px}}
@media(prefers-reduced-motion:reduce){.wtr__big .ic-rays,.wtr__big .ic-cl,.wtr__big .ic-d,.wtr__it{animation:none}}// Weerwidget met eigen iconen · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w=root.querySelector('.wtr');if(!w)return;
function sun(cx,cy,r){var g='<g class="ic-rays" style="transform-box:view-box;transform-origin:'+cx+'px '+cy+'px">';for(var i=0;i<8;i++){var a=i*Math.PI/4,r1=r+2,r2=r+4.2;g+='<line class="ic-l ic-r" x1="'+(cx+r1*Math.cos(a)).toFixed(2)+'" y1="'+(cy+r1*Math.sin(a)).toFixed(2)+'" x2="'+(cx+r2*Math.cos(a)).toFixed(2)+'" y2="'+(cy+r2*Math.sin(a)).toFixed(2)+'"/>';}return g+'</g><circle class="ic-s" cx="'+cx+'" cy="'+cy+'" r="'+r+'"/>';}
var CL='M7 19h9.5a4 4 0 0 0 .4-8 5.5 5.5 0 0 0-10.5 1.6A3.2 3.2 0 0 0 7 19z';
var IC={zon:sun(12,12,4.5),half:sun(15.5,8.5,3.4)+'<g class="ic-cl"><path class="ic-c" d="'+CL+'"/></g>',wolk:'<g class="ic-cl"><path class="ic-c" d="'+CL+'"/></g>',
regen:'<g class="ic-cl"><path class="ic-c" d="M7 15h9.5a4 4 0 0 0 .4-8 5.5 5.5 0 0 0-10.5 1.6A3.2 3.2 0 0 0 7 15z"/></g><g><line class="ic-d" x1="9" y1="18" x2="8.3" y2="20.5"/><line class="ic-d" x1="12.5" y1="18" x2="11.8" y2="20.5"/><line class="ic-d" x1="16" y1="18" x2="15.3" y2="20.5"/></g>',
maan:'<path class="ic-l" style="fill:#fff" d="M16.5 15.8A6.5 6.5 0 0 1 9.2 6a6.5 6.5 0 1 0 7.3 9.8z"/>'};
var NM={zon:'zonnig',half:'half bewolkt',wolk:'bewolkt',regen:'regen',maan:'helder'};
function svg(k){return '<svg viewBox="0 0 24 24" aria-hidden="true">'+IC[k]+'</svg>';}
w.querySelector('.wtr__big').innerHTML=svg('half');
var D={u:[['15:00','half',14],['16:00','wolk',13],['17:00','regen',12],['18:00','regen',11],['19:00','wolk',11],['20:00','maan',10]],
d:[['vr','regen',13,8],['za','half',15,9],['zo','zon',17,10],['ma','wolk',14,9],['di','half',15,8]]};
var list=w.querySelector('.wtr__list'),tabs=[].slice.call(w.querySelectorAll('.wtr__tabs button'));
var tid='wtr-'+Math.random().toString(36).slice(2,7);tabs.forEach(function(t,i){t.id=tid+'-'+i;});
function render(p){list.innerHTML=D[p].map(function(r,i){var tp=p==='u'?r[2]+'°':r[2]+'° <small>'+r[3]+'°</small>';var lab=p==='u'?r[0]+', '+NM[r[1]]+', '+r[2]+' graden':{vr:'vrijdag',za:'zaterdag',zo:'zondag',ma:'maandag',di:'dinsdag'}[r[0]]+', '+NM[r[1]]+', '+r[2]+' tot '+r[3]+' graden';
return '<li class="wtr__it" style="--i:'+i+'" aria-label="'+lab+'"><span class="wtr__tm" aria-hidden="true">'+r[0]+'</span><span class="wtr__ic">'+svg(r[1])+'</span><span class="wtr__tp" aria-hidden="true">'+tp+'</span></li>';}).join('');
var on=tabs.filter(function(t){return t.dataset.p===p;})[0];list.setAttribute('aria-labelledby',on.id);}
function sel(t,f){tabs.forEach(function(x){var on=x===t;x.setAttribute('aria-selected',on?'true':'false');x.tabIndex=on?0:-1;});if(f)t.focus();render(t.dataset.p);}
tabs.forEach(function(t,i){t.addEventListener('click',function(){sel(t);});t.addEventListener('keydown',function(e){var j=e.key==='ArrowRight'?i+1:e.key==='ArrowLeft'?i-1:null;if(j===null)return;e.preventDefault();sel(tabs[(j+tabs.length)%tabs.length],true);});});
render('u');
}
init(document.querySelector('.jouw-container'));
Meer uit cijfers & grafieken
Iets gezien dat je mooi vindt?
Zet het in je selectie en stuur hem op. Dan bouwen we je site eromheen, in jouw huisstijl.
Neem contact op →