marcman
marcman

Reputation: 3383

How to make absolutely positioned elements responsive?

I am trying to make an interactive tag-cloud using Bootstrap elements. It comes out okay, but I've positioned the different tags using absolute positioning from the top and left of the surrounding div. It's pasted below, but because it's quite a bit of code, I've made this fiddle with the code too (note: the snippet is intended to be viewed at full desktop screen width).

However, because I've used absolute positioning, I lose the responsiveness that Bootstrap columns provide. What happens instead is multi-word tags break onto multiple lines, tags end up overlapping each other, and other unwanted behavior.

I'd like to make the tag-cloud responsive as well, but I'm not quite sure how to do it. It seems that to do this with media queries, I'd need to sample the widths pretty frequently. Another idea was to use JQuery to adjust the positions (and maybe font sizes) based on window width, but that doesn't solve the problem either.

My ultimate goal is to maintain the same relative positions of the inner divs (i.e. the tags) while the screen size changes. At some point, the columns can stack, but until the columns stack, I'd like to be able to maintain the same tag layout even if that means reducing the empty space between the tags or even reducing the font size of the tags. In both cases I'd like to make the changes proportionate to the changes in screen size.

So, how can I make this tag cloud responsive to screen size change while maintaining the layout of the inner div "tags"?

.tmp{
	background-color: #000;
	height: 600px;
}

.tagcloud{
	font: "Arial Bold";
	font-weight: bolder;
	height: 600px;
	background-color: #202020;
	position: relative;
	text-align: center;
	min-width: 700px;
}

.tagcloud div{
	position: absolute;
}

.tagcloud a{
	text-decoration: none;
	color: inherit;
}

.tagcloud a:hover{
	text-decoration: underline;
}

.tagcloud .l1{
	font-size: 80px;
	cursor: pointer;
}

.tagcloud .l2{
	font-size: 68px;
	cursor: pointer;
}

.tagcloud .l3{
	font-size: 56px;
	cursor: pointer;
}

.tagcloud .l4{
	font-size: 44px;
	cursor: pointer;
}

.tagcloud .l5{
	font-size: 38px;
	cursor: pointer;
}


#item1{
	color: #c9d35f;
	top: 10px;
	left: 150px;
}

#item2{
	color: #09c9b9;
	top: 210px;
	left: 440px;
}
#item3{
	color: #ba612e;
	top: 410px;
	left: 310px;
}
#item4{
	color: #4b7711;
	top: 275px;
	left: 130px;
}
#item5{
	color: #1bb1fc;
	top: 130px;
	left: 560px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container-fluid">
  <div class="row">
    <div class="col-sm-6 tmp"></div>
    <div class="col-sm-6 col-centered tagcloud">
      <div class="l1" id="item1">
        <a data-container="body" data-toggle="popover" data-trigger="hover" data-placement="top" data-content="Some text">
          First Item</a>
      </div>
      <div class="l2" id="item2">
        <a data-container="body" data-toggle="popover" data-trigger="hover" data-placement="top" data-content="Some text">
          Another Item
        </a>
      </div>
      <div class="l3" id="item3">
        <a data-container="body" data-toggle="popover" data-trigger="hover" data-placement="top" data-content="Some text">
          Item3
        </a>
      </div>
      <div class="l4" id="item4">
        <a data-container="body" data-toggle="popover" data-trigger="hover" data-placement="top" data-content="Some text">
          Item4
        </a>
      </div>
      <div class="l5" id="item5">
        <a data-container="body" data-toggle="popover" data-trigger="hover" data-placement="top" data-content="Some text">
          Item5
        </a>
      </div>
    </div>
  </div>
</div>

Upvotes: 0

Views: 265

Answers (2)

Haroon R.
Haroon R.

Reputation: 302

You can use vw units in CSS3 to set the font-size property. This will cause the tags to scale according to the width of the browser:

W3Schools - CSS Units

The position of the tags should also be set using either % (if they are in a container) or vh and vw units (if your tag cloud fills the entire window). In your case this would most likely mean using percentage units for your top and left CSS properties.

Doing all of this will mean that both the text size and position will be relative to the browser viewport.

However, it will only give you partial browser support. If you need to support older browsers, you can use vUnit.js instead.

Optionally:

You could also combine CSS with a fallback, by using Modernizr to check for Viewport Unit support - you could then use CSS for newer browsers, and vUnit for older ones.

Multi-word links breaking to new lines can be prevented by using:

.tagcloud a { white-space: nowrap; }

Once your columns collapse (say, at mobile width), you might want to stack the tags vertically, so the fonts don't become too small. If that's the case, you can use a media query to remove the absolute positioning from the div elements, and also change the font sizes if you like.

Upvotes: 1

Gaurav Kumar
Gaurav Kumar

Reputation: 336

Use Responsive embed

Allow browsers to determine video or slideshow dimensions based on the width of their containing block by creating an intrinsic ratio that will properly scale on any device.

Rules are directly applied to 

<iframe>, <embed>, <video>,

and  elements; optionally use an explicit descendant class .embed-responsive-item when you want to match the styling for other attributes.

Pro-Tip! You don't need to include frameborder="0" in your s as we override that for you.

<!-- 16:9 aspect ratio --> 
<div class="embed-responsive embed-responsive-16by9"> 
<iframe class="embed-responsive-item" src="..."></iframe> 
</div>
 <!-- 4:3 aspect ratio --> 
<div class="embed-responsive embed-responsive-4by3"> 
<iframe class="embed-responsive-item" src="..."></iframe>
</div>

For more detail refer: https://getbootstrap.com/docs/3.3/components/#responsive-embed

Upvotes: 0

Related Questions