Any problems with using a pseudo-element to space paragraphs with CSS? - html

What I have done most of the time to space paragraphs (or paragraphs and other elements) is to use the ::before tag. For example
p + p::before {
content: '';
display: block;
margin: 20px 0;
}
That way, I can be really specific about my whitespace. For example, I could also do this
h1 + p::before {
content: '';
display: block;
margin: 10px 0;
}
That way I know how the space between each element behaves.
Is this good practice?
On most places I have read that margins and padding should be used exclusively, but I found that I depend too much on id selectors when using them.
On the same topic, if I were to use them, should I use margin or paddings? On some places I have read that margins are prefered, yet on others that padding should be used for typography. By typography I refer to the main body of text: titles, paragraphs, and everything it may contain.
Of course, I would like to avoid <div>s on my HTML code, trying to keep it as semantic as possible.

Is this good practice?
No, not really. That's sacrificing valuable pseudo-elements that could be used for generated content or other clever layout tricks (every element can only have one ::before pseudo-element at a time), to do something that can be done conventionally with margins on the elements themselves.
The typical practice for spacing paragraphs is to specify vertical margins on each paragraph and allow margin collapsing to do the rest:
p {
margin: 20px 0;
}
... because this is what margin collapsing was designed for: so authors can say, "There should be 20px of space between paragraphs", without them having to calculate how much margin each paragraph should have on either end. In other words, this is how CSS implements the concept of paragraph spacing as seen in word processors.
If you don't want this behavior, you need only specify either a top or bottom margin, and change the value of that top or bottom margin wherever it needs to differ. For example:
p {
margin: 20px 0 0 0; /* Equivalent to margin: 0; margin-top: 20px; */
}
h1 + p {
margin-top: 10px;
}
Using pseudo-elements for this is unnecessary.
On most places I have read that margins and padding should be used exclusively, but I found that I depend too much on id selectors when using them.
On the same topic, if I were to use them, should I use margin or paddings? On some places I have read that margins are prefered, yet on others that padding should be used for typography.
This is too broad to answer concisely, but I will say that margins and padding can be used together in some situations as they serve different purposes in layout.
That being said, whenever you find yourself wondering if you should use one or the other, as a starting point consider what they were designed for: margins create space outside an element (that can interact with other margins in various ways); padding creates space inside an element to give its children breathing room away from its content edge. Again, there are a number of situations where it's not so simple, but unfortunately it would be too broad to cover in one answer.
It's not clear to me what that hearsay refers to by "typography".

Using margins and padding in tandem under CSS would allow you to have more freedom of how much white space you want between your elements or borders. Use padding to determine how much space u want in between elements within a closed border such as div or a table, etc. When you want to deal with white space involving elements that aren't restricted to borders or a certain boundary, use margin. Both margin and padding allow you to determine how much space you want to the right, left, top, and bottom of the element of your choosing.

Related

Floated element "steals" width from a following block element inside a display:table container

I have a div that's "floated" to the centre with display:table; margin:auto; (green box)
Inside this, I have a float:left element (red box, which is not always present), then a number of display:block; "lines" (lime boxes). The application is poetry formatting with drop capitals and reverse indentation:
https://jsfiddle.net/nktj94gd/2/
The problem is that the floated "L" is "stealing" its own width from the lime blocks, rather than allowing the outer block (green) to expand to prevent the lime lines wrapping when they do not have to.
I'd really like to avoid having lines wrap when they don't have to, but I cannot set the width of the overall box (it could be from a few em to 100%) .Is there a way to achieve this?
I would use an extra wrapper inside that I make slightly bigger considering the width of L
.outer {
display: table;
margin: auto;
overflow:auto;
outline: 1px solid green;
}
.outer > div {
width:calc(100% + 2.8em); /* 2.8em is an approximation of L width */
transform:translateX(-1.4em); /* rectify the centring */
}
.dropcap {
float: left;
}
.dropcap-inner {
font-size: 4em;
line-height: 1em;
margin-right: 1em;
border: 1px solid red;
}
.line {
display: block;
text-indent: -4em;
margin-left: 4em;
border: 1px solid lime;
}
<div class="outer">
<div>
<span class="dropcap"><span class="dropcap-inner">L</span></span>
<span class="line">orem ipusm dolor sit amet</span>
<span class="line">Lorem ipusm dolor sit amet dddd</span>
</div>
</div>
you probably found some more practical solution to this a year ago, but this is a fairly obscure problem I ran into while also styling poetry, so I figured I'd post my solution in case anyone else needs it :) Hope your poem project worked out, OP!
I think probably most people use <br /> and ::first-letter or something and thus never run into the problem. It's ultimately just a problem of how to preserve intended whitespace (linebreaks mainly) with a pretty dropcap, which is niche, but falls apart quick if you're designing responsively and avoiding hard breaks. (I was using whitespace: pre because it had indented stanzas) ¯\_(ツ)_/¯
How to fix OP's issue: table CSS and wrappers (responsive, markup-dependent), see: https://jsfiddle.net/eja5mnuk/
Stick the spans and the float in a container div
Change display: block on the spans to display: table-row; since your outer is display: table, and you don't impose widths anywhere here, the 'table' will simply expand to accommodate both the float and the linebox
Optionally, display: table-caption on an inner part of the dropcap (not truly necessary, but in OP's code so why not: https://jsfiddle.net/thn2x5zc/)
Everything is integrated into a table formatting context, but we aren't getting unwanted collapse that messes up sizing
This is responsive and doesn't care what your drop cap is. It runs into overflow issues if the drop cap and poem are both too big, you can shove whatever behaviour you want on this bad case if you want (like overflow: hidden on the dropcap, controlling their whitespace/widths, etc....)
It does care about your container structure and margin collapse a lot, so if your code were different, you'd need a different display value, likely something putting table-row/table-cell on a block.
Of course this does have quirks relating to how browsers treat table elements by default, though - mainly auto-collapsed borders, like in a <table>.
Method #2: ::first-letter pseudo-selector, white-space: pre, margin/padding etc. (things other people might use) see: https://jsfiddle.net/3oghpj0w/
These things are all very janky/contradictory secretly, but since ::first-letter is a pretty standard way to style drop caps, and marking up/styling your lines individually may be inconvenient, it is how I ran into the problem lol.
If it's ::first-letter, we're using a block-level element to hold the poem text. The most basic way is just to apply width: min-content; to that block's container to get it to sort of take away the float's contribution (since it's larger). Then you can add padding-right to that container to re-accommodate borders, margins, etc. (If the margin between the drop cap and poem is 3em, add 3em back to the right.)
Fixes of this style do not re-integrate the float with the poem, so the poem will still have overflow issues. But it's sufficient for fixing simple alignment problems :)
Some notes
The float contributes size to the block e.g. via its margins - floated margins don't collapse, generally, which is part of our problem here. But the container won't expand for things out of flow, and thus the float pushes its siblings into overflow (poetry is highly sensitive to wrapping and whitespace)
Ultimately, most ways the browser can calculate the size of text wrappers ignore the float (it's out of flow); everything skews towards occupying space along the inline and block axis (horizontal/vertical, here), based on everything's sizing, margins, wrapping, and other inline/block contexts, ref: https://developer.mozilla.org/en-US/docs/Web/CSS/display
Tables are the ancestors of most responsive text framing
Sorry this is so long! A lot of conventional fixes break when you care about the shape of the whitespace and can't treat text as a block, which makes a lot of search results very inapplicable.

Why margin collapse it's not applied to the html tag? [duplicate]

The CSS2 box model tells us that adjoining vertical margins collapse.
I find it quite annoying, being the source of many design bugs. I hope that by understanding the purpose of collapsing margins, I will understand when to use them and how to avoid them when they are not needed.
What is the purpose of this feature?
The general meaning of "margin" isn't to convey "move this over by 10px" but rather, "there must be 10px of empty space beside this element."
I've always found this is easiest to conceptualize with paragraphs.
If you just gave paragraphs margin-top: 10px and had no margins on any other elements, a series of paragraphs would be spaced beautifully. But of course, you'd run into trouble when placing another element underneath a paragraph. The two would touch.
If margins didn't collapse, you'd hesitate to add margin-bottom: 10px to your previous code, because then any pair of paragraphs would get spaced 20px apart, while paragraphs would separate from other elements by only 10px.
So vertical margins collapse. By adding top and bottom margins of 10px you're saying, "I don't care what margin rules any other elements have. I demand at least 10px of padding above and below each of my paragraphs."

Why display=inline-block adds uncontrollable vertical margins

I'm trying to fiddle my problem on http://jsfiddle.net and have got strangest behaviour there. Can you please explain where these (http://jsfiddle.net/C6V3S/) vertical margins come from? Does appear on jsfiddle.net (at least in Chrome and FF), do not appear when copy/pasting to local standalone file ...
works OK afer changing to simple block
Sample for standalone test file:
.btn {
padding: 0px;
border: 1px solid red;
display: inline-block;
}
.txt {
display: inline-block;
width: 12px;
height: 12px;
border: none;
padding: 0;
margin: 0;
background: #77FF77;
}
</style>
<div class="btn"><div class="txt"></div></div>
When you make the .txt element inline-block, it is taken into the text flow of the parent .btn element. At that point, the line-height of .btn kicks in, which is larger than the height of the .txt element.
So, add .btn {line-height: 10px;} (for example) and your problem is fixed. I saw you already tried to influence the line-height of the inner .txt element, so you were pretty close with your attempts. Adjusting the font-size would work as well, since the default line-height is formula-based on the font-size. Anyway, the key is to do that on the parent element, not the child element.
You don't have this problem when you make the inner element a block, because then there's no text-like content, so there's no line-height applied at all.
inline-block is brilliant and convenient for so many cases. But they come with one annoying pitfall: unnecessary whitespace. As you're nesting an inline-block within an inline-block, that results in a white-space disaster. You can read all about whitespace and inline-blocks on David Walsh's blog.
There are many ways to handle this, but my favorite (and most widely supported) solution is setting this to the parent inline-block element:
.btn {
font-size: 0;
}
Here is an example of before/after:
http://jsfiddle.net/C6V3S/1/
This is not caused by whitespace (you don't have any inside the divs in your HTML), nor by putting inline-block inside of another inline-block. This is caused because of the line-height of the outer div. As you can see from the below fiddle, the current line-height of the red-border div has a line-height that is being set by the browser (and it varies from browser to browser), and as long as there is something inside of the div that takes up space as an inline or inline-block item, the height will be affected by the line-height.
There are many ways around this, and they all pretty much do the same thing:
1) Take the inside element out of flow, and then reinsert it back in. This will make the outer div think that there is nothing inside of it, and try to become as small as possible, and then fill up space exactly around the element when it inserted back in. The easiest way to do this is by floating it.
2) Make the outer element take up no space. This will make the inside element define the height and width of its parent. If you do font-size: 0, as mentioned before, this will make the outer element think that the inline inside element takes up no space, and therefore not take up any space itself, and wrap itself tightly around the inner element. This can be done by setting line-height: 0 as well (which is a perfect fix for the problem, as the problem is line-height).
There are other ways to make the parent element not have its line-height, but that should get you started.
http://jsfiddle.net/C6V3S/4/
It's "just how it works," but it can be worked around. The easiest way to fix it would be to set negative margins on .btn. It should work for any modern browser (IE8 and above, if I recall). Floating the elements should achieve what you want, too. As a wholly different solution if your problem with it is merely aesthetic, you can just wrap the elements in a parent, set that parent's background-color to what you want, and not worry about its child elements' backgrounds. They'll be transparent to whatever is beneath them, and you'll get rid of those visual breaks.
If you want to stick with negative margins on with display: inline-block, but need that pesky first element not to jump leftward out of its parent, you could target it explicitly:
.btn {
margin-left: -4px;
}
.btn:first-of-type {
margin-left: 0px;
}
Edit: After reading another answer, I'm not sure if I understood the question -- do you mean the margin atop the elements (which would be horizontal) or the margin to the sides (vertical)?

Weird margin differences between Chrome/Safari and Firefox

I recently designed a website (http://willryan.us/typefun01), mainly using Chrome while coding to test. I recently noticed that there are some weird things happening at the end of certain sections, (the gap after History, the overlap of Styles onto Anatomy).
I have a css reset in my stylesheet (not sure if that has anything to do with this), and I can't figure out what's causing this, and how to get the site to look like how it does when viewed in Chrome
The gap after History is due to:
#historyWide {
margin: 250px 80px 75px;
}
It could be remedied with:
div#content > div {
overflow: hidden; /* or auto */
}
You could also move the large top and bottom margins of elements inside the child divs of #content to padding on the child divs themselves. Anything will work as long as it's all contained by those child divs.
You're simply seeing the different ways that browsers handle imperfect layout.
If you want to avoid the gap after History you would want to use a padding in historyWide instead of a margin; the margin pulls aways elements while padding makes them bigger
On anatomy what's happening is that you're using the property "top" to modify #styles, this will move the element but the parent will reserve only the original space for the element. You will be better off working with margins and padding than with "top" if you have to keep a relation between the elements.
Lastly, i woulnt position elements with margins like you did with #stylesMono. I think you could better work with paragraphs to keep keep the vertical position and, from there, working with floats, margin and padding in the scope of the "p".

Is there a need for zero-out DIV's margin and padding?

I wonder if on any browser div element comes with a preset margin/padding value other than zero. As far as I know, div and span come with zero padding and margin values by standard to make them suitable canvas for style decoration.
Even better, is there a definite standard for default styles for all elements that is cross-browser which we can make assumptions upon? For instance FORM comes with top/bottom margins, OL/UL come with padding-left's.
I occasionally see a
* {
margin: 0;
padding: 0;
}
and this just looks like a dirty hack without knowing the reasons or consequences. Anyone has any better approach to this?
Different browsers have different defaults -- this is why using CSS resets like these
http://meyerweb.com/eric/tools/css/reset/
http://developer.yahoo.com/yui/reset/
are popular in order to insure that browsers are treating all the elements equally. It gives you a baseline and then expects you to define all the relevant styling.