I agree with the other answers, your problem requires you set the transaction scope on an enclosing container to Required. Unless you have altered the inner objects, their default transaction level is Supported which means they will enlist in an transaction if available. A Required settings will start a transaction and for completeness, NotSupported indicates that the Executable/Container will ignore any existing transactions which may result in deadlocks depending on your design.
I built out a sample package that drops and recreates a target table to verify transactions are behaving as expected. There are 3 data flows in the package, each one adding a unique value to the table (1, 2, 4) so that a query like this will indicate whether values arrived in the destination table.
SELECT count(1) AS rc, sum(T.col1) AS Total FROM dbo.TrxTest T
As you can see, there are 7 variables, 3 in pairs. The FailDataFlow named ones are booleans that allow any of the unique data flows to fail/succeed. This is accomplished by causing a divide by 0 exception in the where clause of the corresponding query.

The Sequence Container has a TransactionOption of Required. The individual data flows retain their default TransactionOption of Supported.
The first execution resulted in an unable to communicate with the distributed transaction coordinator as it was set to manual startup on this VM. Correcting that problem resulted in the package correctly failing out as "DFT value 2" generated a divide by zero exception. Running the query way above showed nothing in my table despite the presence of a green box on "DFT Value 1".

Switching the value of FailDataFlow1 to False and re-running showed values of 3 and 7 respectively in my query which indicates all rows arrived.
You can further explore by changing transaction options on various containers/executables to assure yourself they are working as the other respondents have indicated.