robynico
robynico

Reputation: 236

SVG : viewbox property strech text inside

I have a histo bar chart with viewbox property on svg element.

I can not find a solution with the text inside which is stretched as you can see below.

Obviously, I don't want to externalize text elements from g elements.

svg path {
    fill: none;
    stroke: #003B56;
}
<svg width="100%" height="100" viewBox="0 0 200 100" preserveAspectRatio="none">
    <g>
        <g transform="translate(0, 0)" class="2013">
            <rect class="ca" width="33.333333333333336" height="100" stroke-width="1" stroke="#ffffff" style="fill: rgb(239, 239, 239);" />
            <rect class="ca" width="16.666666666666668" shape-rendering="crispEdges" x="8.333333333333334" height="0" y="95" style="fill: rgb(58, 58, 58);" />
            <text shape-rendering="crispEdges" dy="10" dx="16.666666666666668" style="text-anchor: middle; font-size: 8px; fill: rgb(140, 140, 140); width: 33.3333%; height: 66.6667%;">2013</text>
            <rect class="marge" x="14.583333333333334" width="4.166666666666667" height="8.333333333333334" y="85" shape-rendering="crispEdges" visibility="hidden" style="fill: rgb(210, 210, 210);" />
        </g>
        <g transform="translate(33.333333333333336, 0)" class="2014">
            <rect class="ca" width="33.333333333333336" height="100" stroke-width="1" stroke="#ffffff" style="fill: rgb(239, 239, 239);" />
            <rect class="ca" width="16.666666666666668" shape-rendering="crispEdges" x="8.333333333333334" height="0" y="95" style="fill: rgb(58, 58, 58);" />
            <text shape-rendering="crispEdges" dy="10" dx="16.666666666666668" style="text-anchor: middle; font-size: 8px; fill: rgb(140, 140, 140); width: 33.3333%; height: 66.6667%;">2014</text>
            <rect class="marge" x="14.583333333333334" width="4.166666666666667" height="8.333333333333334" y="85" shape-rendering="crispEdges" visibility="hidden" style="fill: rgb(210, 210, 210);" />
        </g>
        <g transform="translate(66.66666666666667, 0)" class="2015">
            <rect class="ca" width="33.333333333333336" height="100" stroke-width="1" stroke="#ffffff" style="fill: rgb(239, 239, 239);" />
            <rect class="ca" width="16.666666666666668" shape-rendering="crispEdges" x="8.333333333333334" height="0" y="95" style="fill: rgb(58, 58, 58);" />
            <text shape-rendering="crispEdges" dy="10" dx="16.666666666666668" style="text-anchor: middle; font-size: 8px; fill: rgb(140, 140, 140); width: 33.3333%; height: 66.6667%;">2015</text>
            <rect class="marge" x="14.583333333333334" width="4.166666666666667" height="8.333333333333334" y="85" shape-rendering="crispEdges" visibility="hidden" style="fill: rgb(210, 210, 210);" />
        </g>
        <g transform="translate(100, 0)" class="2015">
            <rect class="ca" width="33.333333333333336" height="100" stroke-width="1" stroke="#ffffff" style="fill: rgb(239, 239, 239);" />
            <rect class="ca" width="16.666666666666668" shape-rendering="crispEdges" x="8.333333333333334" height="65.32792098352175" y="29.67207901647825" style="fill: rgb(58, 58, 58);" />
            <text shape-rendering="crispEdges" dy="10" dx="16.666666666666668" style="text-anchor: middle; font-size: 8px; fill: rgb(140, 140, 140); width: 33.3333%; height: 66.6667%;">2015</text>
            <rect class="marge" x="14.583333333333334" width="4.166666666666667" height="8.333333333333334" y="75.76149333828752" shape-rendering="crispEdges" visibility="visible" style="fill: rgb(210, 210, 210);" />
        </g>
        <g transform="translate(133.33333333333334, 0)" class="2016">
            <rect class="ca" width="33.333333333333336" height="100" stroke-width="1" stroke="#ffffff" style="fill: rgb(239, 239, 239);" />
            <rect class="ca" width="16.666666666666668" shape-rendering="crispEdges" x="8.333333333333334" height="70" y="25" style="fill: rgb(58, 58, 58);" />
            <text shape-rendering="crispEdges" dy="10" dx="16.666666666666668" style="text-anchor: middle; font-size: 8px; fill: rgb(140, 140, 140); width: 33.3333%; height: 66.6667%;">2016</text>
            <rect class="marge" x="14.583333333333334" width="4.166666666666667" height="8.333333333333334" y="73.65632455308725" shape-rendering="crispEdges" visibility="visible" style="fill: rgb(210, 210, 210);" />
        </g>
        <g transform="translate(166.66666666666669, 0)" class="2017">
            <rect class="ca" width="33.333333333333336" height="100" stroke-width="1" stroke="#ffffff" style="fill: rgb(239, 239, 239);" />
            <rect class="ca" width="16.666666666666668" shape-rendering="crispEdges" x="8.333333333333334" height="27.544350652682226" y="67.45564934731777" style="fill: rgb(58, 58, 58);" />
            <text shape-rendering="crispEdges" dy="10" dx="16.666666666666668" style="text-anchor: middle; font-size: 8px; fill: rgb(140, 140, 140); width: 33.3333%; height: 66.6667%;">2017</text>
            <rect class="marge" x="14.583333333333334" width="4.166666666666667" height="8.333333333333334" y="81.50817238857238" shape-rendering="crispEdges" visibility="visible" style="fill: rgb(210, 210, 210);" />
        </g>
        <path transform="translate(114.58333333333333, 20)" class="data" d="M0,60.761493338287515L33.333333333333336,58.656324553087245L66.66666666666667,66.50817238857238" style="stroke: rgb(210, 210, 210);" />
    </g>
</svg>

Upvotes: 0

Views: 241

Answers (1)

ccprog
ccprog

Reputation: 21811

The best you can do is divide your SVG into two parts: the stretched bars, and the unstretched caption. Use an inner svg with preserveAspectRatio="none" for the bars, and position the captions with percentages. You cannot use transform attributes for that.

svg path {
    fill: none;
    stroke: #003B56;
}
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100">
    <svg width="100%" height="100" viewBox="0 0 200 100" preserveAspectRatio="none">
        <g transform="translate(0, 0)" class="2013">
            <rect class="ca" width="33.333333333333336" height="100" stroke-width="1" stroke="#ffffff" style="fill: rgb(239, 239, 239);" />
            <rect class="ca" width="16.666666666666668" shape-rendering="crispEdges" x="8.333333333333334" height="0" y="95" style="fill: rgb(58, 58, 58);" />
            <rect class="marge" x="14.583333333333334" width="4.166666666666667" height="8.333333333333334" y="85" shape-rendering="crispEdges" visibility="hidden" style="fill: rgb(210, 210, 210);" />
        </g>
        <g transform="translate(33.333333333333336, 0)" class="2014">
            <rect class="ca" width="33.333333333333336" height="100" stroke-width="1" stroke="#ffffff" style="fill: rgb(239, 239, 239);" />
            <rect class="ca" width="16.666666666666668" shape-rendering="crispEdges" x="8.333333333333334" height="0" y="95" style="fill: rgb(58, 58, 58);" />
            <rect class="marge" x="14.583333333333334" width="4.166666666666667" height="8.333333333333334" y="85" shape-rendering="crispEdges" visibility="hidden" style="fill: rgb(210, 210, 210);" />
        </g>
        <g transform="translate(66.66666666666667, 0)" class="2015">
            <rect class="ca" width="33.333333333333336" height="100" stroke-width="1" stroke="#ffffff" style="fill: rgb(239, 239, 239);" />
            <rect class="ca" width="16.666666666666668" shape-rendering="crispEdges" x="8.333333333333334" height="0" y="95" style="fill: rgb(58, 58, 58);" />
            <rect class="marge" x="14.583333333333334" width="4.166666666666667" height="8.333333333333334" y="85" shape-rendering="crispEdges" visibility="hidden" style="fill: rgb(210, 210, 210);" />
        </g>
        <g transform="translate(100, 0)" class="2015">
            <rect class="ca" width="33.333333333333336" height="100" stroke-width="1" stroke="#ffffff" style="fill: rgb(239, 239, 239);" />
            <rect class="ca" width="16.666666666666668" shape-rendering="crispEdges" x="8.333333333333334" height="65.32792098352175" y="29.67207901647825" style="fill: rgb(58, 58, 58);" />
            <rect class="marge" x="14.583333333333334" width="4.166666666666667" height="8.333333333333334" y="75.76149333828752" shape-rendering="crispEdges" visibility="visible" style="fill: rgb(210, 210, 210);" />
        </g>
        <g transform="translate(133.33333333333334, 0)" class="2016">
            <rect class="ca" width="33.333333333333336" height="100" stroke-width="1" stroke="#ffffff" style="fill: rgb(239, 239, 239);" />
            <rect class="ca" width="16.666666666666668" shape-rendering="crispEdges" x="8.333333333333334" height="70" y="25" style="fill: rgb(58, 58, 58);" />
            <rect class="marge" x="14.583333333333334" width="4.166666666666667" height="8.333333333333334" y="73.65632455308725" shape-rendering="crispEdges" visibility="visible" style="fill: rgb(210, 210, 210);" />
        </g>
        <g transform="translate(166.66666666666669, 0)" class="2017">
            <rect class="ca" width="33.333333333333336" height="100" stroke-width="1" stroke="#ffffff" style="fill: rgb(239, 239, 239);" />
            <rect class="ca" width="16.666666666666668" shape-rendering="crispEdges" x="8.333333333333334" height="27.544350652682226" y="67.45564934731777" style="fill: rgb(58, 58, 58);" />
            <rect class="marge" x="14.583333333333334" width="4.166666666666667" height="8.333333333333334" y="81.50817238857238" shape-rendering="crispEdges" visibility="visible" style="fill: rgb(210, 210, 210);" />
        </g>
        <path transform="translate(114.58333333333333, 20)" class="data" d="M0,60.761493338287515L33.333333333333336,58.656324553087245L66.66666666666667,66.50817238857238" style="stroke: rgb(210, 210, 210);" />
    </svg>
    <g shape-rendering="crispEdges" style="text-anchor: middle; font-size: 8px; fill: rgb(140, 140, 140);">
        <text dy="10" dx="8.3333333333333333%">2013</text>
        <text dy="10" dx="25%">2014</text>
        <text dy="10" dx="41.666666666666667%">2015</text>
        <text dy="10" dx="58.333333333333333%">2015</text>
        <text dy="10" dx="75%">2016</text>
        <text dy="10" dx="91.666666666666667%">2017</text>
    </g>
</svg>

You could equally position the rectangles using percentages for the horizontal values (x and width, again no transform attribute anywhere), and avoid placing them inside the inner svg. Albeit, for the path this is impossible.

Upvotes: 1

Related Questions